光说不练假把式,不如上手试试,这篇来写个有点卵用的东西。
- TCP Server -
用 Go 实现一个 TCP Server 实在是太简单了,什么 c10k problem、select、poll、epoll、kqueue、iocp、libevent,通通不需要(但为了通过面试你还是得去看呀),只需要这样两步:
监听端口 1080(socks5的默认端口)
每收到一个请求,启动一个 goroutine 来处理它
搭起这样一个架子,实现一个 Hello world,大约需要 30 行代码:
func main() {
server, err := net.Listen("tcp", ":1080")
if err != nil {
fmt.Printf("Listen failed: %v\n", err)
return
}
for {
client, err := server.Accept()
if err != nil {
fmt.Printf("Accept failed: %v", err)
continue
}
go process(client)
}
}
func process(client net.Conn) {
remoteAddr := client.RemoteAddr().String()
fmt.Printf("Connection from %s\n", remoteAddr)
client.Write([]byte("Hello world!\n"))
client.Close()
}
- SOCKS5 -
socks5 是 SOCKS Protocol Version 5 的缩写,其规范定义于 RFC 1928[1],感兴趣的同学可以自己去翻一翻。
它是个二进制协议,不那么直观,不过实际上非常简单,主要分成三个步骤:
认证
建立连接
转发数据
我们只需 16 行就能把 socks5 的架子搭起来:
func process(client net.Conn) {
if err := Socks5Auth(client); err != nil {
fmt.Println("auth error:", err)
client.Close()
return
}
target, err := Socks5Connect(client)
if err != nil {
fmt.Println("connect error:", err)
client.Close()
return
}
Socks5Forward(client, target)
}
这样一看是不是特别简单?
然后你只要把 Socks5Auth、Socks5Connect 和 Socks5Forward 给补上,一个完整的 socks5 代理就完成啦!是不是就像画一匹马一样简单?
全文完 (不是)
- Socks5Auth -
言归正传,socks5 协议规定,客户端需要先开口:
RFC 1928,首行是字段名,次行是字节数
解释一下:
VER | 本次请求的协议版本号,取固定值 0x05(表示socks 5) |
NMETHODS | 客户端支持的认证方式数量,可取值 1~255 |
METHODS | 可用的认证方式列表 |
我们用如下代码来读取客户端的发言: