本篇文章仅供技术交流,请遵循相关国家法律法规,作者不提供任何技术支持
没啥思路,文章暂时搁置 - 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 的作用,其实就是在本地和远程服务器之间,建立了一条抽象的虚拟加密通道