-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
62 lines (29 loc) · 35.8 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>SOCKS 5 代理协议</title>
<link href="/2023/07/18/SOCKS-5/"/>
<url>/2023/07/18/SOCKS-5/</url>
<content type="html"><![CDATA[<p>参考:<br><a href="https://www.rfc-editor.org/rfc/rfc1928">RFC 1928: SOCKS Protocol Version 5</a><br><a href="https://www.rfc-editor.org/rfc/rfc1929">RFC 1929: Username/Password Authentication for SOCKS V5</a></p><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>SOCKS 5描述的协议是对SOCKS 4协议的升级. 关于SOCKS 4的介绍可以查看本博客先前的post: <a href="https://cccxg.github.io/2023/07/07/SOCKS-4-4A/">SOCKS 4/4A TCP代理协议</a></p><p>SOCKS 5协议旨在为TCP和UDP域中的C/S架构应用程序提供一种框架, 以便应用程序可以方便, 安全地使用代理服务穿过防火墙. 从概念上来看, SOCKS 5协议作用于应用层和传输层之间, 因此不为网络层提供服务, 例如转发ICMP消息. 相比SOCKS 4, SOCKS 5进行了以下扩展: 支持UDP, 多种通用的认证方案, 支持域名/IPv6的寻址策略. </p><p>与SOCKS 4类似, SOCKS 5的服务过程也可以分为两个阶段:</p><ol><li>代理请求: 客户端建立与SOCKS服务端的TCP连接, 并发送代理请求. 服务端可以根据请求的内容回复接受或者拒绝. 若接受请求, 则服务端建立对应的连接为后续数据转发做准备.</li><li>转发数据: 请求过程完成后, SOCKS服务端仅需简单地在客户端与目标主机之间转发数据即可.</li></ol><p>SOCKS 5支持TCP和UDP, 同时也定义了CONNECT操作与BIND操作, 并额外定义了一个UDP ASSOCIATE操作. </p><p><strong>Note:</strong> 尽管都支持CONNECT操作与BIND操作, 但是SOCKS 5与SOCKS 4并不兼容, SOCKS 5定义了新的数据包形式, 所以SOCKS 5服务器无法解析SOCKS 4请求. CONNECT与BIND的一致是概念上的, 而不是形式上的. </p><h2 id="基于TCP的客户端操作步骤"><a href="#基于TCP的客户端操作步骤" class="headerlink" title="基于TCP的客户端操作步骤"></a>基于TCP的客户端操作步骤</h2><p>当一个TCP客户端希望连接到一个仅能通过防火墙访问的目标主机时, 它可以通过建立一个到SOCKS服务端对应端口的TCP连接来实现. SOCKS服务通常监听1080端口. 客户端到服务端的TCP连接建立成功后, 客户端: 1.进入认证方法协商阶段, 2.使用指定的方法进行身份认证, 3.发送转发请求. 服务端评估转发请求, 建立对应的连接或拒绝请求. </p><p>除非特殊说明, 后文数据包中的数字都表示对应字段的字节长度. <code>0xhh</code>表示该字段的值为指定值. <code>Variable</code>表示对应字段的值的字节长度可变.</p><p>客户端连接到SOCKS服务端后首先发送版本标识符/认证方法协商消息:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"> +-----+----------+----------+</span><br><span class="line"> | VER | NMETHODS | METHODS |</span><br><span class="line"> +-----+----------+----------+</span><br><span class="line"> | 1 | 1 | 1 to 255 |</span><br><span class="line"> +-----+----------+----------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VER: SOCKS版本号, 此处为0x05.</span><br><span class="line"> - NMETHODS: 客户端支持的认证方法数量.</span><br><span class="line"> - METHODS: 客户端支持的认证方法列表, 每一个字节对应一种认证方法. </span><br></pre></td></tr></table></figure><p>SOCKS服务端选择指定的认证方法, 并回复客户端:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"> +-----+--------+</span><br><span class="line"> | VER | METHOD |</span><br><span class="line"> +-----+--------+</span><br><span class="line"> | 1 | 1 |</span><br><span class="line"> +-----+--------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VER: SOCKS版本号, 此处为0x05.</span><br><span class="line"> - METHOD: 服务端指定的认证方法</span><br><span class="line"> - 0x00: 无需认证.</span><br><span class="line"> - 0x01: GSSAPI(Generic Security Services API).</span><br><span class="line"> - 0x02: 用户名密码认证.</span><br><span class="line"> - 0x03 ~ 0x7F: IANA保留.</span><br><span class="line"> - 0x80 ~ 0xFE: 保留的私有方法.</span><br><span class="line"> - 0xFF: 没有接受的方法(服务端支持的方法未在客户端提供的方法列表中给出).</span><br></pre></td></tr></table></figure><p>随后, SOCKS服务端与客户端进入指定认证方法的认证阶段. 不同的认证方法的认证流程由不同的协议规定, 后面的章节将介绍基于用户名密码的认证方法(RFC 1929). </p><p>认证阶段结束后, 客户端将发送代理请求的详细信息. 如果协商的认证方法包括了完整性的校验和/或机密性的封装,这些请求必须使用对应的方法封装. </p><p>SOCKS代理请求形式如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"> | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |</span><br><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"> | 1 | 1 | 0x00 | 1 | Variable | 2 |</span><br><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VER: SOCKS协议版本, 此处为0x05.</span><br><span class="line"> - CMD:</span><br><span class="line"> - 0x01: CONNECT操作.</span><br><span class="line"> - 0x02: BIND操作.</span><br><span class="line"> - 0x03: UDP ASSOCIATE操作.</span><br><span class="line"> - RSV: 保留字段.</span><br><span class="line"> - ATYPE: 目标主机地址类型</span><br><span class="line"> - 0x01: IPv4.</span><br><span class="line"> - 0x03: Domain name.</span><br><span class="line"> - 0x04: IPv6.</span><br><span class="line"> - DST.ADDR: 目标主机地址</span><br><span class="line"> - IPv4 4个字节.</span><br><span class="line"> - Domain name n+1个字节, 第一个字节表示域名长度n, 后续n个字节为域名.</span><br><span class="line"> - IPv6 16个字节.</span><br><span class="line"> - DST.PORT: 目标主机端口.</span><br></pre></td></tr></table></figure><p>身份认证流程结束后, 客户端立即向服务端发送代理请求. 服务端评估请求, 并且返回如下形式的回复:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"> | VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |</span><br><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"> | 1 | 1 | 0x00 | 1 | Variable | 2 |</span><br><span class="line"> +-----+-----+-------+------+----------+----------+</span><br><span class="line"></span><br><span class="line">其中: </span><br><span class="line"> - VER: SOCKS协议版本, 此处为0x05.</span><br><span class="line"> - REP: 回复状态代码</span><br><span class="line"> - 0x00: 成功.</span><br><span class="line"> - 0x01: 服务端错误.</span><br><span class="line"> - 0x02: 规则集禁止访问.</span><br><span class="line"> - 0x03: 网络不可达.</span><br><span class="line"> - 0x04: 主机不可达.</span><br><span class="line"> - 0x05: 连接被拒.</span><br><span class="line"> - 0x06: TTL超时.</span><br><span class="line"> - 0x07: 不支持的CMD操作符.</span><br><span class="line"> - 0x08: 不支持的目标主机地址类型.</span><br><span class="line"> - 0x09 ~ 0xFF: 未指定.</span><br><span class="line"> - RSV: 保留字符, 固定为0x00.</span><br><span class="line"> - ATYP: 绑定地址类型</span><br><span class="line"> - 0x01: IPv4.</span><br><span class="line"> - 0x03: Domain name.</span><br><span class="line"> - 0x04: IPv6.</span><br><span class="line"> - BND.ADDR: 服务端(与目标主机的连接)绑定的地址.</span><br><span class="line"> - BND.PORT: 服务端(与目标主机的连接)绑定的端口.</span><br></pre></td></tr></table></figure><p>如果先前选择的认证方法包含用于身份验证, 完整性和(或)机密性的封装, 则SOCKS服务端的回复也将被对应方法封装.</p><p>当回复信息为失败(REP不等于0)时, SOCKS服务端必须在发送回复后关闭TCP连接, 这之间的间隔不应该超过10秒. </p><p>当回复信息为成功(REP等于0), 并且代理请求的操作类型是CONNCET或BIND时, 客户端接收到回复即可以开始传输数据. 如果先前选择的认证方法包含用于身份验证, 完整性和(或)机密性的封装, 则客户端传输的数据也将被对应方法封装. 类似地, 当目标主机发送给客户端的数据数据到达SOCKS服务端时, 服务端必须按照对应的方法封装后再转发给客户端. </p><h3 id="CONNECT"><a href="#CONNECT" class="headerlink" title="CONNECT"></a>CONNECT</h3><p>SOCKS服务端对CONNECT请求(客户端代理请求中CMD为0x01)的回复中, BND.PORT表示服务端分配的连接到目标主机的端口号. 同理, BND.ADDR包含被分配的IP. 通常, 服务端提供的用于连接目标主机的IP与客户端连接服务端所使用的IP并不相同, 因为服务端通常是多地址的. 服务端应该使用目标主机地址, 端口以及客户端的源IP, 端口评估是否接受CONNECT代理请求. </p><h3 id="BIND"><a href="#BIND" class="headerlink" title="BIND"></a>BIND</h3><p>BIND代理请求适用于客户端需要接受从目标主机发起的入站连接的情况. FTP是一个常见的例子, FTP使用客户端到目标主机的主要连接传输命令以及状态报告, 而使用目标主机到客户端的连接传输数据.</p><p>SOCKS协议所预期的行为是: 客户端应用协议在使用CONNECT代理请求成功建立主要连接后才使用BIND代理请求用于建立第二个连接. SOCKS服务端将使用BIND代理请求中的目标主机地址及端口评估是否接受请求.</p><p>BIND操作期间SOCKS服务端将向客户端回复两次消息. 第一次回复发送于服务端创建并且绑定一个新的socket时. 回复中的BND.PORT字段包含服务端分配的用于监听入站连接的端口. 回复中的BND.ADDR字段包含服务端分配的用于监听入站连接的IP. 客户端需要将这两个字段通知(通过主要连接或者控制连接)目标主机. 第二次回复发送于目标主机到服务端的入站连接建立成功或失败时. 第二次回复中的BND.PORT及BND.ADDR字段包含服务端所连接到的主机的地址. </p><h3 id="UDP-ASSOCIATE"><a href="#UDP-ASSOCIATE" class="headerlink" title="UDP ASSOCIATE"></a>UDP ASSOCIATE</h3><p>UDP ASSOCIATE代理请求用于建立UDP连接以转发UDP数据报. DST.ADDR, DST.PORT包含客户端用于发送UDP数据包的地址及端口. SOCKS服务端可以使用这些信息限制访问. 如果客户端在建立UDP连接时不拥有这些信息, 则客户端必须使用全零的端口号和地址. </p><p>客户端与SOCKS服务端之间的TCP连接(客户端与服务端协商认证方法, 发送代理请求时所使用的TCP连接)中止时, 后续的UDP连接也随之中止. </p><p>SOCKS服务端针对UDP ASSOCIATE的回复中, BND.PORT, BND.ADDR指定了用于转发的地址及端口, 客户端必须发送需要转发的UDP信息到服务端指定的地址及端口. </p><h2 id="基于UDP的客户端操作步骤"><a href="#基于UDP的客户端操作步骤" class="headerlink" title="基于UDP的客户端操作步骤"></a>基于UDP的客户端操作步骤</h2><p>SOCKS服务端接收来自客户端的UDP ASSOCIATE代理请求, 后会评估代理请求, 请求通过后, 服务端分配一个端口用于监听该客户端的UDP数据报, 并通过代理请求回复消息中的BND.PORT字段通知客户端对应的端口. 运行在这个端口上的监听程序称为UDP转发服务端.</p><p>UDP客户端必须发送需要转发的UDP数据报到UDP转发服务端上. 如果先前选择的认证方法包含用于身份验证, 完整性和(或)机密性的封装, 则客户端传输的UDP数据报也将使用对应方法封装. 每一个UDP数据包携带如下头部: </p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"> +-----+------+------+----------+----------+----------+</span><br><span class="line"> | RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |</span><br><span class="line"> +-----+------+------+----------+----------+----------+</span><br><span class="line"> | 2 | 1 | 1 | Variable | 2 | Variable |</span><br><span class="line"> +-----+------+------+----------+----------+----------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - RSV: 保留字段, 必须为0x0000.</span><br><span class="line"> - FRAG: UDP数据报的编号.</span><br><span class="line"> - ATYPE: 目标主机地址类型.</span><br><span class="line"> - 0x01: IPv4.</span><br><span class="line"> - 0x03: Domain name.</span><br><span class="line"> - 0x04: IPv6.</span><br><span class="line"> - DST.ADDR: 目标主机地址.</span><br><span class="line"> - IPv4 4个字节.</span><br><span class="line"> - Domain name n+1个字节, 第一个字节表示域名长度n, 后续n个字节为域名.</span><br><span class="line"> - IPv6 16个字节.</span><br><span class="line"> - DST.PORT: 目标主机端口.</span><br><span class="line"> - DATA: 携带的数据. </span><br></pre></td></tr></table></figure><p>UDP转发服务端决定转发UDP数据包时, 服务端不会向客户端返回任何消息, 仅仅是安静的转发数据. 类似地, 当服务端丢弃UDP数据包或者无法转发时, 也不会通知客户端. 当转发服务端接收到目标主机的回复数据报时, 服务端也会使用上面的头部信息以及身份认证方法对应的方法来封装UDP数据包. </p><p>UDP转发服务端必须从SOCKS服务端取得它所服务的客户端IP地址, 并且丢弃任何来源于其他地址的数据报(每个转发服务端都是为了服务唯一一个客户端而建立的).</p><p>FRAG字段表示该UDP数据报是不是一系列的数据报中的一个片段. 0x00表示独立的数据报. 1~127表示该片段在整体中的顺序编号, 最高位的1比特用于表示是否为最后一个片段. 对每一个数据报序列, 其消息接收者(转发服务端)都将维护一个组装队列以及组装计时器. 当计时器超时, 或者最新接收到的数据报片段的FRAG字段值小于已接收的数据报片段中的最大值时, 组装队列将被重置并且丢弃已接收的相关数据报片段. 组装计时器的超时时间不能小于5秒. 建议应用程序应该尽量避免碎片化传输. </p><p>SOCKS服务端对于是否支持数据报组装是可选的; 不支持的服务端应该丢弃任何FRAG字段不为0x00的数据报.</p><h2 id="用户名密码认证过程"><a href="#用户名密码认证过程" class="headerlink" title="用户名密码认证过程"></a>用户名密码认证过程</h2><p>当客户端支持用户名密码认证, 并且服务端指定的方法为用户名密码认证时(<code>METHOD</code>字段值为<code>0x02</code>), 客户端与服务端进入身份认证的子协商阶段. 该阶段始于客户端提交的用户名密码请求:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"> +-----+------+----------+------+----------+</span><br><span class="line"> | VER | ULEN | UNAME | PLEN | PASSWD |</span><br><span class="line"> +-----+------+----------+------+----------+</span><br><span class="line"> | 1 | 1 | 1 to 255 | 1 | 1 to 255 |</span><br><span class="line"> +-----+------+----------+------+----------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VER: 当前子协商的版本, 此处为0x01.</span><br><span class="line"> - ULEN: 用户名的长度.</span><br><span class="line"> - PLEN: 密码长度.</span><br><span class="line"> - UNAME: 用户名.</span><br><span class="line"> - PASSWD: 密码.</span><br></pre></td></tr></table></figure><p>服务端将验证用户名和密码, 并回复:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> +-----+--------+</span><br><span class="line"> | VER | STATUS |</span><br><span class="line"> +-----+--------+</span><br><span class="line"> | 1 | 1 |</span><br><span class="line"> +-----+--------+</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VER: 子协商版本, 此处为0x01.</span><br><span class="line"> - STATUS: </span><br><span class="line"> - 0x00 - 认证成功.</span><br><span class="line"> - 其他 - 认证失败.</span><br></pre></td></tr></table></figure><p>若认证失败时, 服务端必须关闭连接. 当认证成功时, 服务端与客户端进入后续的协商阶段(代理请求, 以及评估代理请求).</p>]]></content>
<categories>
<category> 计算机网络 </category>
<category> SOCKS代理 </category>
</categories>
</entry>
<entry>
<title>SOCKS 4/4A TCP代理协议</title>
<link href="/2023/07/07/SOCKS-4-4A/"/>
<url>/2023/07/07/SOCKS-4-4A/</url>
<content type="html"><![CDATA[<p>参考:<br><a href="https://www.openssh.com/txt/socks4.protocol">SOCKS: A protocol for TCP proxy across firewalls</a><br><a href="https://www.openssh.com/txt/socks4a.protocol">SOCKS 4A: A Simple Extension to SOCKS 4 Protocol</a></p><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>SOCKS(Protocol for sessions traversal across firewall securely, 防火墙安全会话转换协议)是一种TCP会话转发协议, 最初由David Koblas提出, 后续由Ying-Da Lee修改并扩展到了第4个版本(SOCKS 4). SOCKS使得用户可以无感知地穿过防火墙访问外部目标. 当每个客户端与SOCKS服务器的TCP会话开始时, SOCKS服务器会先进行访问控制, 随后SOCKS服务器仅需简单地在客户端与目标主机间转发数据. 因为该协议独立于应用层的协议, 所以可以(已经)被许多不同的服务所使用, 如: telnet, ftp, finger, whois, gopher, www, 等等. 同时SOCKS 4也适用于程序使用加密来保护数据的情况. </p><h2 id="SOCKS-4"><a href="#SOCKS-4" class="headerlink" title="SOCKS 4"></a>SOCKS 4</h2><p>SOCKS 4的服务过程整体可以分为两个部分:</p><ol><li>代理请求: 客户端建立与SOCKS服务端的TCP连接, 并发送代理请求. 服务端可以根据请求的内容回复接受或者拒绝. 若接受请求, 则服务端建立对应的连接为后续数据转发做准备.</li><li>转发数据: 请求过程完成后, SOCKS服务端仅需简单地在客户端与目标主机之间转发数据即可.</li></ol><p>SOCKS 4代理请求中定义了两种操作: <strong>CONNECT</strong>与<strong>BIND</strong>.</p><h3 id="CONNECT"><a href="#CONNECT" class="headerlink" title="CONNECT"></a>CONNECT</h3><p>CONNECT是SOCKS中最常用的操作. 当客户端希望主动与目标主机建立连接时, 客户端连接到SOCKS服务端并发送一个CONNECT代理请求. 请求数据包中包括目标主机的IP, 端口, 以及客户端用户id等. CONNECT请求形式如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"> +----+----+----+----+----+----+----+----+----+----+....+----+</span><br><span class="line"> | VN | CD | DSTPORT | DSTIP | USERID |NULL|</span><br><span class="line"> +----+----+----+----+----+----+----+----+----+----+....+----+</span><br><span class="line">字节长度 1 1 2 4 可变长度 1</span><br><span class="line"></span><br><span class="line">其中: </span><br><span class="line"> - VN: SOCKS协议版本, 此处值应为4.</span><br><span class="line"> - CD: SOCKS操作码, CONNECT对应的值为1.</span><br><span class="line"> - DSTPORT: 目标主机端口.</span><br><span class="line"> - DSTIP: 目标主机IP.</span><br><span class="line"> - USERID: 用户id.</span><br><span class="line"> - NULL: 结束符, 一个全0字节.</span><br></pre></td></tr></table></figure><p>SOCKS服务端根据客户端IP, 用户id, 目标主机IP, 目标主机端口, 以及可能携带的认证信息(IDENT, 参见RFC 1413)来确定是否接受客户端CONNECT代理请求. 若接受请求, 服务端建立一个到目标主机指定端口的TCP连接. 当服务端到目标主机的连接建立成功, 或服务端拒绝了客户端请求, 或服务端操作失败(无法连接到目标)时, 服务端向客户端发送如下形式的回复:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"> +----+----+----+----+----+----+----+----+</span><br><span class="line"> | VN | CD | DSTPORT | DSTIP |</span><br><span class="line"> +----+----+----+----+----+----+----+----+</span><br><span class="line">字节长度 1 1 2 4</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VN: 回复码版本, 此处值应为0.</span><br><span class="line"> - CD: 结果代码</span><br><span class="line"> - 90: 请求准许.</span><br><span class="line"> - 91: 请求被拒或操作失败.</span><br><span class="line"> - 92: 请求被拒, 因为服务端无法连接到客户端的identd(参见RFC 1413).</span><br><span class="line"> - 93: 请求被拒, 因为客户端和identd(参见RFC 1413)报告了不一样的用户id.</span><br><span class="line"> - DSTPORT, DSTIP: 无实际意义, 仅是为了兼容性考虑(后文BIND操作的回复中有实际含义).</span><br></pre></td></tr></table></figure><p>当SOCKS服务端操作失败或拒绝客户端代理请求时, 服务端向客户端发送回复消息后立即关闭它们之间的连接. 对于成功的请求, 服务端向客户端发送回复消息后立即开始进行双向数据转发. 客户端可以直接在它与服务端的连接上进行I/O操作, 就好像它直接连接到了目标主机一样. </p><h3 id="BIND"><a href="#BIND" class="headerlink" title="BIND"></a>BIND</h3><p>BIND操作适用于客户端需要接受一个由目标主机发起的入站连接的情况. 入站连接的建立必须发生在从客户端到目标主机的主要连接已经建立之后. 当不使用代理时, 这个过程通常是如下的一系列操作:</p><ol><li>客户端获取一个socket, 以及对应的IP, 端口.</li><li>客户端监听socket, 并通过主要连接通知目标主机对应的IP, 端口.</li><li>客户端接受由目标主机主动发起的入站连接.</li></ol><p>SOCKS BIND操作的目标就是通过代理支持上述操作, 重点是入站连接是从目标主机连接到SOCKS服务端, 而不是连接到客户端. </p><p><strong>Note:</strong> BIND操作所做的就是在SOCKS服务端获取一个等待入站连接的socket, 将这个socket所绑定的IP及端口通知给客户端, 并在这个socket上监听来自目标主机的入站连接. 将socket绑定的IP及端口通知给目标主机是客户端的工作, 服务端并不关心客户端具体如何通知目标主机. 在BIND操作之前, 需要客户端与目标主机已经建立了一条主要连接, 使得客户端可以通知目标主机需要连接的socket IP及端口. 通常主要连接是客户端提前通过SOCKS CONNECT操作建立好的. (协议原文这部分写的比较晦涩, 很容易产生歧义, 让人误以为主要连接的建立是BIND操作的一部分, 事实上它们是无关的). </p><p>BIND操作中客户端向SOCKS服务端发送如下形式的代理请求:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> +----+----+----+----+----+----+----+----+----+----+....+----+</span><br><span class="line"> | VN | CD | DSTPORT | DSTIP | USERID |NULL|</span><br><span class="line"> +----+----+----+----+----+----+----+----+----+----+....+----+</span><br><span class="line">字节长度 1 1 2 4 可变长度 1</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VN: SOCKS协议版本号, 此处为4.</span><br><span class="line"> - CD: SOCKS操作码, BIND对应的值为2.</span><br><span class="line"> - DSTPORT, DSTIP: 目标应用服务端口, IP.</span><br><span class="line"> - USERIP: 用户id.</span><br><span class="line"> - NULL: 全0字节</span><br></pre></td></tr></table></figure><p>SOCKS服务端根据上述代理请求信息, 以及客户端源IP等信息, 确认是否接受客户端的请求. 服务端对BIND请求的回复CONNECT请求回复形式一致:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"> +----+----+----+----+----+----+----+----+</span><br><span class="line"> | VN | CD | DSTPORT | DSTIP |</span><br><span class="line"> +----+----+----+----+----+----+----+----+</span><br><span class="line">字节长度 1 1 2 4</span><br><span class="line"></span><br><span class="line">其中:</span><br><span class="line"> - VN: 回复码版本, 此处值应为0.</span><br><span class="line"> - CD: 结果代码</span><br><span class="line"> - 90: 请求准许.</span><br><span class="line"> - 91: 请求被拒或操作失败.</span><br><span class="line"> - 92: 请求被拒, 因为SOCKS服务端无法连接到客户端的identd(参见RFC 1413).</span><br><span class="line"> - 93: 请求被拒, 因为客户端和identd(参见RFC 1413)报告了不一样的用户id.</span><br></pre></td></tr></table></figure><p>与CONNECT代理请求的回复不同的是, 当一个BIND请求被接受时, SOCKS服务端的回复中的DSTIP, DSTPORT字段是有实际含义的. 在BIND操作下服务端将获取一个socket, 等待由目标主机发起的入站连接, 同时将该socket所绑定的IP及端口通过DSTIP, DSTPORT字段回复给客户端(第一次回复). 当DSTIP字段值为0时, 客户端需要使用它所连接的服务端的IP来替换该字段的值(当服务端不是一个多地址主机时将出现这种情况). </p><p>客户端程序的应用协议必须提供一个可以将这两个值从客户端发送到目标主机的方法, 从而使得目标主机可以主动发起并建立连接. 通常, 在BIND操作前客户端就已经通过SOCKS CONNECT操作建立了与目标主机的主要连接, 客户端将通过主要连接通知目标主机socket所绑定的IP及端口. </p><p>当从目标主机到SOCKS服务端的连接建立成功后, 服务端再次向客户端发送回复(第二次回复). 服务端检查该连接的源IP与客户端BIND请求中的DSTIP是否一致. 若不一致, 第二个回复的CD字段设为91, 并且服务端关闭两端的连接. 若一致, CD字段设为90, 并且服务端开始在两个连接上转发流量. 随后对于客户端来说, 只需要对它到服务端的连接进行正常的I/O操作, 就好像它直接连接到了目标主机一样. </p><p>无论对于CONNECT还是BIND操作, 服务端都设置了一个与目标主机建立连接的时间限制(目前CSTC实现中设为2分钟). 若超时仍未建立与目标主机的连接, 则SOCKS服务端放弃连接并断开与客户端的连接.</p><h2 id="SOCKS-4A"><a href="#SOCKS-4A" class="headerlink" title="SOCKS 4A"></a>SOCKS 4A</h2><p>SOCKS 4A针对客户端无法进行域名解析的情况做了简单的扩展. </p><p>在SOCKS 4A中, 当客户端无法解析目标主机的IP地址时, 仅需将上文所述的代理请求数据包中的DSTIP字段的前三个字节设为0, 并将最后一个字节设为非0值, 对应IP 0.0.0.x, x不为0. 根据IANA(The Internet Assigned Numbers Authority, 互联网数字分配机构)的规定, 这样的地址是不允许作为IP地址的, 因此如果客户端可以解析域名, 就不应该出现. 请求数据包在NULL字节结尾之后, 客户端必须继续添加目标主机的域名并以另一个NULL字节结尾. 这同时适用于CONNECT和BIND操作. </p><p>当服务端使用SOCKS 4A协议时, 必须检查代理请求数据包中的DSTIP字段. 若对应的IP地址为0.0.0.x, x不为0, 则服务端必须读取请求数据包中携带的域名. 服务端应该解析域名并且建立到目标主机的连接. </p><p>服务端可能会传递它无法解析的域名给下一跳的SOCKS服务器.</p>]]></content>
<categories>
<category> 计算机网络 </category>
<category> SOCKS代理 </category>
</categories>
</entry>
<entry>
<title>Hello World</title>
<link href="/2023/06/13/Hello-World/"/>
<url>/2023/06/13/Hello-World/</url>
<content type="html"><![CDATA[<h2 id="Level-1"><a href="#Level-1" class="headerlink" title="Level 1"></a>Level 1</h2><h3 id="Level-2"><a href="#Level-2" class="headerlink" title="Level 2"></a>Level 2</h3><p>Context:<br>Hello world.<br>Hello world.</p><p>Code</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">HelloWorld</span><span class="params">()</span></span>{</span><br><span class="line"> fmt.Println(<span class="string">"hello world"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Table</p><table><thead><tr><th>a</th><th>b</th><th>c</th></tr></thead><tbody><tr><td>1</td><td>2</td><td>4</td></tr></tbody></table><p>Math<br>$$ y = \alpha * x^2 + \beta $$</p><p>List</p><ul><li>aaa</li><li>bbb</li><li>ccc<ul><li>ddd</li></ul></li></ul>]]></content>
</entry>
</search>