0%

介绍

HMAC(Hash-based Message Authentication Code是一种基于哈希函数的消息认证码(MAC)算法,用于验证数据的完整性和真实性。它通过结合哈希算法与密钥来生成一个认证码,可以防止数据在传输过程中被篡改。HMAC 广泛应用于网络协议(如 TLSIPSec 等)、数字签名以及 API 认证等场景中。

在这篇文章中,我们将深入了解 HMAC 的原理,并通过具体的计算过程来说明其如何工作。

阅读全文 »

TLS 1.2 与 TLS 1.3 握手流程深度解析:安全与性能的演进

引言

TLS(传输层安全协议)是互联网加密通信的基石。从 TLS 1.2TLS 1.3,协议在安全性和性能上实现了质的飞跃。本文将深入对比两者的握手流程,解析其设计差异,并探讨为何 TLS 1.3 成为现代网络通信的首选。


阅读全文 »

常见加密模式

为什么要分模式?

对称加密算法(如AES)只能加密固定长度的数据块(比如 AES 的块是 128 位)。如果要加密一个很长的文件,就需要将文件切分成多个块,再逐个加密。

问题来了:如何让这些块之间产生关联,避免被破解?这就是加密模式的作用!

阅读全文 »

AirDrop

  • 打开
    1
    launchctl load /System/Library/LaunchAgents/com.apple.sharingd.plist
  • 关闭
    1
    launchctl unload /System/Library/LaunchAgents/com.apple.sharingd.plist

Bluetooth

  • 关闭
    1
    2
    3
    4
    defaults write /Library/Preferences/com.apple.Bluetooth.plist ControllerPowerState 0

    killall bluetoothd
    killall blued

CD

  • eject
    1
    2
    3
    for (DRDevice *device in [DRDevice devices]) {
    [device ejectMedia];
    }

USB

使用 Disk Arbitration framework

Disk Arbitration framework 是一个基于 Core Foundation 的低级框架。会在磁盘出现和消失时通知您的应用程序,并让您的应用程序影响该过程。借助 Disk Arbitration,我们可以:

  • 检测何时出现新磁盘
  • 阻止挂载
  • 使用不同的标志或在不同的安装点上安装卷
  • 卸载卷
  • 观察卷的变化

1. 文件系统事件:文件变动的探测器

文件系统事件是macOS提供的一个API,可以帮助我们监听文件或目录的变更。只要文件或目录发生变化,这个API就会发出通知。

阅读全文 »

如何修改 Git提交历史中的 author 等信息

修改上次提交的commit信息

1
2
3
git commit --amend --author="newname<newmail>"
// 不想修改提交信息,则添加--no-edit
git commit --amend --author="newname<newmail>" --no-edit

cherry-pick 冲突

Git 中,若想选择性保留冲突文件的原始版本(当前分支的版本)或合并来的版本(被 cherry-pick 的提交版本),可以通过以下命令实现:

1. 保留当前分支的原始版本

1
2
3
4
5
6
7
8
# 针对特定冲突文件(例如你的 xxx.cpp)
git checkout --ours src/xxx.cpp

# 标记冲突已解决
git add src/xxx.cpp

# 继续完成 cherry-pick 流程
git cherry-pick --continue

2. 保留合并来的版本(冲突文件以被 cherry-pick 的提交内容为准)

1
2
3
4
5
6
7
8
# 针对特定冲突文件
git checkout --theirs src/xxx.cpp

# 标记冲突已解决
git add src/xxx.cpp

# 继续完成 cherry-pick 流程
git cherry-pick --continue

关键概念说明:

  • –ours:代表当前分支的版本(即你在执行 cherry-pick 时的本地原始状态)。

  • –theirs:代表被 cherry-pick 的提交的版本(即你要合并进来的修改)。

补充说明:

如果多个文件冲突,可以批量操作:

1
2
3
4
5
# 保留所有文件的当前分支版本
git checkout --ours .

# 或保留所有文件的合并来的版本
git checkout --theirs .

(操作后仍需 git addgit cherry-pick --continue

如果中途想彻底放弃整个 cherry-pick,仍可用:

1
git cherry-pick --abort

1. 引言

在网络通信中,HTTP 代理是一个常见的工具,用于在客户端和服务器之间中转HTTP请求和响应。它可以用于多种目的,包括提升安全性、管理网络流量、提高访问速度等。

2. HTTP代理的基本概念

代理服务器的定义:代理服务器(Proxy Server)是一种位于客户端和目标服务器之间的中间服务器,用于转发客户端的请求并将服务器的响应返回给客户端。

HTTP 协议基础:HTTPHypertext Transfer Protocol)是用于分布式、协作式和超媒体信息系统的应用层协议,是万维网数据通信的基础。

3. HTTP代理的工作原理

请求流程:

客户端发送 HTTP 请求到代理服务器。
代理服务器接收请求并将其转发给目标服务器。
目标服务器处理请求并返回响应给代理服务器。
代理服务器将响应返回给客户端

响应流程:

与请求流程类似,代理服务器在请求和响应过程中充当中间人角色。

数据传输和处理:

代理服务器可以对传输的数据进行缓存、过滤和修改。

1
2
3
4
5
6
7
+--------+     HTTP Request     +-----------+    HTTP Request     +-----------+
| Client |--------------------->| Proxy |-------------------->| Target |
| | | Server | | Server |
+--------+ +-----------+ +-----------+
<--------------------- <----------------
HTTP Response HTTP Response

4. HTTP代理的类型

普通代理

HTTP 客户端向代理发送请求报文,代理服务器需要正确地处理请求和连接(例如正确处理 Connection: keep-alive),同时向服务器发送请求,并将收到的响应转发给客户端。 这种代理扮演的是「中间人」角色,对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送 HTTP 报文。

1
2
3
4
5
6
7
➜  ~ curl -vvv http://baidu.com
* Trying 39.156.66.10:80...
* Connected to baidu.com (39.156.66.10) port 80
> GET / HTTP/1.1
> Host: baidu.com
> User-Agent: curl/8.4.0
> Accept: */*
1
2
3
4
5
6
7
8
➜  ~ curl -vvv -x http://127.0.0.1:8080 http://www.baidu.com
* Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET http://www.baidu.com/ HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/8.4.0
> Accept: */*
> Proxy-Connection: Keep-Alive

完整路径

Proxy-Connection

Connection,以及 Connection 定义的其它 Header,只是对上个节点和当前节点之间的连接进行说明,必须在报文转给下个节点之前删除,否则可能会引发后面要提到的问题。其它不能传递的 Header 还有Prxoy-AuthenticateProxy-ConnectionTransfer-EncodingUpgrade

「close」表示操作完成后需要关闭当前连接;Connection 还允许任何字符串作为它的值,如「my-connection」,用来存放自定义的连接说明。HTTP/1.0 默认不支持持久连接,很多 HTTP/1.0 的浏览器和服务器使用「Keep-Alive」这个自定义说明来协商持久连接:浏览器在请求头里加上 Connection: Keep-Alive,服务端返回同样的内容,这个连接就会被保持供后续使用。对于 HTTP/1.1Connection: Keep-Alive 已经失去意义了,因为 HTTP/1.1 除了显式地将 Connection 指定为 close,默认都是持久连接。

有了上面的背景知识,我们来看问题。互联网上,存在着大量简陋并过时的代理服务器在继续工作,它们很可能无法理解 Connection——无论是请求报文还是响应报文中的 Connection。而代理服务器在遇到不认识的 Header 时,往往都会选择继续转发。大部分情况下这样做是对的,很多使用 HTTP 协议的应用软件扩展了 HTTP 头部,如果代理不传输扩展字段,这些软件将无法工作。

如果浏览器对这样的代理发送了 Connection: Keep-Alive,那么结果会变得很复杂。这个 Header 会被不理解它的代理原封不动的转给服务端,如果服务器也不能理解就还好,能理解就彻底杯具了。服务器并不知道 Keep-Alive 是由代理错误地转发而来,它会认为代理希望建立持久连接,服务端同意之后也返回一个 Keep-Alive。同样,响应中的 Keep-Alive 也会被代理原样返给浏览器,同时代理还会傻等服务器关闭连接——实际上,服务端已经按照 Keep-Alive 指示保持了连接,即使数据回传完成,也不会关闭连接。另一方面,浏览器收到 Keep-Alive 之后,会复用之前的连接发送剩下的请求,但代理不认为这个连接上还会有其他请求,请求被忽略。这样,浏览器会一直处于挂起状态,直到连接超时。

这个问题最根本的原因是代理服务器转发了禁止转发的 Header。但是要升级所有老旧的代理也不是件简单的事,所以浏览器厂商和代理实现者协商了一个变通的方案:首先,显式给浏览器设置代理后,浏览器会把请求头中的 Connection 替换为 Proxy-Connetion。这样,对于老旧的代理,它不认识这个 Header,会继续发给服务器,服务器也不认识,代理和服务器之间不会建立持久连接(不能正确处理 Connection 的都是 HTTP/1.0 代理),服务器不返回 Keep-Alive,代理和浏览器之间也不会建立持久连接。而对于新代理,它可以理解 Proxy-Connetion,会用 Connection 取代无意义的 Proxy-Connection,并将其发送给服务器,以收到预期的效果。

显然,如果浏览器并不知道连接中有老旧代理的存在,或者在老旧代理任意一侧有新代理的情况下,这种方案仍然无济于事。所以有时候服务器也会选择彻底忽略 HTTP/1.0Keep-Alive 特性:对于 HTTP/1.0 请求,从不使用持久连接,也从不返回 Keep-Alive

隧道代理

HTTP 客户端通过 CONNECT 方法请求隧道代理创建一条到达任意目的服务器和端口的 TCP 连接,并对客户端和服务器之间的后继数据进行盲转发。详见 RFC 7231 - HTTP/1.1: Semantics and Content

http隧道代理

Socket 编程中的端口复用:SO_REUSEADDR 和 SO_REUSEPORT

欢迎来到一个充满移植性挑战的世界!在深入分析这两个选项之前,我们首先需要了解 BSD 套接字实现是所有套接字实现的鼻祖。几乎所有其他系统都在某个时间点复制了 BSD 套接字实现,或至少是其接口,然后在此基础上发展演变。当然,BSD 套接字实现本身也在不断演变,因此那些更晚期复制它的系统获得了更早期系统所缺乏的功能。理解 BSD 套接字实现是理解其他所有套接字实现的关键,即使你不打算为 BSD 系统编写代码,也应该了解它。

在深入探讨 SO_REUSEADDRSO_REUSEPORT 之前,你需要了解一些基本知识。一个 TCP/UDP 连接由五个值组成的元组标识:

1
{<协议>, <源地址>, <源端口>, <目标地址>, <目标端口>}

任何唯一的这些值组合标识一个连接。因此,没有两个连接可以具有相同的五个值,否则系统将无法区分这些连接。

套接字的基本操作

  1. 创建套接字:使用 socket() 函数设置套接字的协议。
  2. 绑定地址和端口:使用 bind() 函数设置源地址和端口。
  3. 连接目标地址和端口:使用 connect() 函数设置目标地址和端口。
    对于 UDP,由于它是无连接协议,可以在不连接的情况下使用。然而,在某些情况下连接它是有益的。在无连接模式下,如果未显式绑定,UDP 套接字通常会在第一次发送数据时由系统自动绑定,因为未绑定的 UDP 套接字无法接收任何(回复)数据。对于未绑定的 TCP 套接字也是如此,它在连接之前会自动绑定。
阅读全文 »

Netfilter,在 Linux 内核中的一个软件框架,用于管理网络数据包。不仅具有网络地址转换(NAT)的功能,也具备数据包内容修改、以及数据包过滤等防火墙功能。利用运作于用户空间的应用软件,如 iptablesnftablesebtablesarptables 等,来控制 Netfilter,系统管理者可以管理通过Linux操作系统的各种网络数据包。1990 年代,NetfilterLinux 2.3.15 版时进入Linux内核,正式应用于 Linux 2.4 版。

阅读全文 »

简介

TCP 快速打开(TCP Fast Open,简称TFO)是对计算机网络中传输控制协议(TCP)连接的一种简化握手手续的拓展,用于提高两端点间连接的打开速度。

它通过握手开始时的 SYN 包中的 TFO cookie(一个 TCP 选项)来验证一个之前连接过的客户端。如果验证成功,它可以在三次握手最终的 ACK 包收到之前就开始发送数据,这样便跳过了一个绕路的行为,更在传输开始时就降低了延迟。这个加密的 Cookie 被存储在客户端,在一开始的连接时被设定好。然后每当客户端连接时,这个 Cookie 被重复返回。

最显著的优点是可以利用握手去除一个往返 RTT

开启 TFO

net.ipv4.tcp_fastopenLinux 内核中的一个配置参数,它用于控制 TCP Fast Open 功能。
具体地,net.ipv4.tcp_fastopen 的值可以是以下几种:

  • 0:禁用 TCP Fast Open 功能。
  • 1:在客户端启用 TCP Fast Open 功能。
  • 2:在服务器端启用 TCP Fast Open 功能。
  • 3:在客户端和服务器端都启用 TCP Fast Open 功能。

通过设置这个参数,可以根据实际需求选择是否启用和在哪一端启用 TCP Fast Open,从而优化网络性能。

阅读全文 »