没啥思路,文章暂时搁置 - 2022-03-02
前言
Socks5 协议
在编写相关代码之前,我们需要先将 Socks5 协议给了解一下
使用 WireShark 抓取 Socks5 报文
$ curl --socks5 157.90.140.29:1080 ip.sb
同时我也将 WireShark 抓取到的报文片段截取下来了,可以点击 下载 后,使用相同的软件进行本地分析
分析Go-Shadowsocks2的源码
tcp.go
// Create a SOCKS server listening on addr and proxy to server.
func socksLocal(addr, server string, shadow func(net.Conn) net.Conn) {
logf("SOCKS proxy %s <-> %s", addr, server)
tcpLocal(addr, server, shadow, func(c net.Conn) (socks.Addr, error) { return socks.Handshake(c) })
}
// Create a TCP tunnel from addr to target via server.
func tcpTun(addr, server, target string, shadow func(net.Conn) net.Conn) {
tgt := socks.ParseAddr(target)
if tgt == nil {
logf("invalid target address %q", target)
return
}
logf("TCP tunnel %s <-> %s <-> %s", addr, server, target)
tcpLocal(addr, server, shadow, func(net.Conn) (socks.Addr, error) { return tgt, nil })
}
- addr:客户端监听地址
- server:客户端连接的地址,也就是远程服务器的地址
而关于 shadow 这个传入的匿名函数,我们可以通过其他地方是如何调用它的来进行作用判断
func main() {
...
ciph, err := core.PickCipher(cipher, key, password)
...
if flags.Socks != "" {
socks.UDPEnabled = flags.UDPSocks
go socksLocal(flags.Socks, addr, ciph.StreamConn)
if flags.UDPSocks {
go udpSocksLocal(flags.Socks, udpAddr, ciph.PacketConn)
}
}
...
}
type Cipher interface {
StreamConnCipher
PacketConnCipher
}
type StreamConnCipher interface {
StreamConn(net.Conn) net.Conn
}
type streamConn struct {
net.Conn
Cipher
r *reader
w *writer
}
func (aead *aeadCipher) StreamConn(c net.Conn) net.Conn { return shadowaead.NewConn(c, aead) }
// NewConn wraps a stream-oriented net.Conn with cipher.
func NewConn(c net.Conn, ciph Cipher) net.Conn { return &streamConn{Conn: c, Cipher: ciph} }
前面通过调用 func PickCipher(...) (Cipher, error)
函数,我们可以得知 ciph
实际上就是 Cipher
结构体,这里 socksLocal
的作用,其实就是在本地和远程服务器之间,建立了一条抽象的虚拟加密通道