vaakian / vaakian.github.io

some notes
https://vaakian.github.io
3 stars 0 forks source link

网络编程(GO) #9

Open vaakian opened 4 years ago

vaakian commented 4 years ago

一、网络编程

注:目前只学习TCP版本

传输层 tcp

服务端使用Listen方法监听一个端口,当客户端需要通信时,使用Dial方法连接服务端。

服务端监听使用net.listen("tcp", "ip:port")

客户端连接net.dial("tcp", "ip:port")

应用层 socks5

1. 建立连接

客户端与服务端建立TCP连接,向服务端发送连接请求,具体如下:

version nmethods methods
1Byte 1Byte 1-255Byte 由nmethods指定

version 代表socks代理版本,目前绝大多数情况使用sock5,即0x05

nmethods 客户端支持的认证方法数量

methods 客户端支持的方法列表,每个方法占用1Byte

METHOD定义

如建立socks5,不需要认证,只支持不需要认认证协议,则数据格式为: 0x05 0x01 0x00

既支持无密码,又支持账号密码认证,数据格式为: 0x05 0x02 0x00 0x02

随后,服务端收到客户端支持的认证列表后,从中挑选一个支持的方法返回给客户端,

version method
1Byte 1Byte

1. 无需认证

服务端返回:0x05 0x00,随后直接开始解包请求,代理客户端的流量。

2. 密码认证 0x05 0x02

服务端返回:0x05 0x02,随后客户端按照以下格式发送账号密码:

VERSION USERNAME_LENGTH USERNAME PASSWORD_LENGTH PASSWORD
1Byte 1Byte 1-255Byte 1Byte 1-255Byte
version: 固定0x05
user_length: 用户名长度
username: 用户名
password_length: 密码长度
password: 密码

举例子:若账号是0xFF,密码是0x0A 0x0B 0x0C,则发送以下数据给服务端: 0x05 0x01 0xFF 0x03 0x0A 0x0B 0x0C。然后服务端收到并响应认证结果。

version status
1Byte 1Byte
version: 固定0x05
status: 0x00认证成功,其余认证失败(可由开发者自由定制)

服务端返回认证成功数据:0x05 0x00

随后客户端会发送连接命令给服务器,代理服务器会连接目标服务器,并返回结果。

客户端请求格式

VERSION COMMAND RSV ADDRESS_TYPE DST.ADDR DST.PORT
1Byte 1Byte 1Byte 1Byte 1-255Byte 2Byte
version: 固定0x05
command: 
    0x01 CONNECT 连接上游服务器
    0x02 BND 绑定,被动模式
    0x03 UDP ACCOCIATE UDP中继
RSV: 保留字段
ADRESS_TYPE:
    0x01 IPv4
    0x03 域名
    0x04 IPv6

目前常用Connect模式:代理服务器收到请求后,代理访问该请请求,并将结果返回给客户端,完成整个连接过程。

golang实现socks5代理

完整代码

vaakian commented 4 years ago

分析 image

vaakian commented 4 years ago

(三层、隧道)传输协议,只传送数据,不对数据做处理。所以转发的端口应该要有一个进程监听并进行正常应答,转发端口只作为client,该端口应该有一个server。

应用层协议,通过某传输协议传送数据,双方进行正常应答。比如tcp、udp,只是一个传输载体协议。

vaakian commented 4 years ago

以gost为例,本地端口转发

gost -L tcp://:80/172.16.0.2:8080 -F socks5://172.16.0.3:1080

本地监听80端口,若监听到请求,将tcp请求(纯请求,此时还没开始传输正式数据)通过socks5转发给172.16.0.3,告诉它我想访问172.16.0.2:8080,随后172.16.0.3和172.16.0.2:8080建立连接,并通过该socks5连接返回172.16.0.2的数据,然后返回给本地80端口请求的客户端。

client -> server -> tell 172.16.0.3 through socks5 1080 to dial 172.16.0.02:8080

实际i/o过程:client <-> server <-> 172.16.0.3 <-> 172.16.0.2

若未指定代理服务器,则通过本地dial转发的端口,否则告诉forward服务器我想dial的目的端口。

比如:gost -L tcp://:1080/172.16.0.4:1080,则是相当于本地开启了socks5代理,但流量都要经过172.16.0.4代理访问。

举一反三

gost -L tcp://:53/127.0.0.1:80 -F socks5://172.16.0.3:1080

此时通过 -F forward服务器访问127.0.0.1,实际上访问的是服务器(172.16.0.3)的80端口。