Socks5代理协议很强大,不光可以实现HTTP/HTTPS代理的TCP隧道代理功能,类似connect,还可以实现HTTP代理不能做到的UDP代理功能。
要知道UDP代理的重要过程,以方便我们排查错误,我们还需要了解Socks5协议对UDP代理方式的流程规定,百度到一篇讲的很好的文章,大家可以参考。
https://blog.csdn.net/whatday/article/details/40183555
我们先来仔细看一下这个过程
首先,我们可以看到,Socks5代理服务器一般只开放一个TCP端口,所以我们在代理服务器上,使用netstat命令是看不到其开放了UDP端口的。因为Socks5服务端通过TCP端口接收客户端发送的代理请求指令,然后分配一个UDP的端口,再通过刚才TCP的连接把这个UDP的IP和端口发送给客户端。客户端下一步只需将UDP包加上特制包头,向这个UDP的端口发送即可。
如果我们做一个原生支持Socks5代理的程序,了解这个过程就可以了,但是如果再工作中遇到第三方的程序,本身不支持UDP代理的,而我们又在公司内网,断了互联网连接,只能通过一个Socks5服务器上网的,该怎么办呢?
UDP协议应用场景不是很多,一般是DNS,音视频聊天,游戏信令等场合。加入我们在内网使用qq或钉钉,虽然其可以配置socks5代理,但是这些软件本身不支持UDP的socks5代理,也就是我们只能聊天,不能进行视频语音通话了。此时,我们就需要透明代理。
支持Socks5的透明代理软件,我最喜欢用的就是redsocks2了,其官方地址为:https://github.com/semigodking/redsocks
redsocks2下载源码之后,安装gcc,然后使用make命令就可以直接在ubuntu或者centos上编译,非常方便,但是注意,要实现UDP协议的透明代理,要使用2019年以前的版本,不可以使用2020的版本,因为作者merge了另一名开发的代码后,解析配置文件会出现错误
下面开始实操
首先我们启动一个Socks5代理服务器,我用的是goproxy,其他开源软件使用dante也行
proxy socks -t tcp -p "0.0.0.0:1080" -g xxx.xxx.xxx.xxx
注意这里-g参数要填你Socks5服务器本身的IP地址,如果有多个IP,必须是透明代理的机器可以访问到的IP地址,也可以不填。这个参数其实就是上图Socks5协议中,UDP穿透回复给发起人的信息。
然后我们找另一台linux机器,CentOS或ubuntu都可以,因为iptables mangle表的限制,我们需要把跑redsocks2的服务器当作路由器来使用,所以需要打开linux内核的转发功能
开启Linux的内核转发方法是,打开/etc/sysctl.conf这个文件,取消掉 net.ipv4.ip_forward=1 这一行的注释.
然后执行
sudo sysctl -p
使修改后的文件配置立即生效。
然后,我们编辑redsocks2的配置文件如下,注意这里的配置文件版本为2019年及之前的
base {
log_debug = on;
log_info = on;
daemon = off;
redirector = iptables;
}
redudp {
local_ip = 192.168.1.16; //localhost
local_port = 12345; //port I will route traffic to
ip = xxx.xxx.xxx.xxx; //socks5 host
port = 1080; //socks5 port
type = socks5; //its socks5 server
//login = rc4-md5; //not used
//password = "your_passwd"; //not used
udp_timeout = 20;
}
然后,我们就可以开始使用iptables配合tproxy开始进行透明代理的转发了。好处是ubuntu、centos哪怕最小化安装,都有tproxy内核模块了,但是openwrt需要单独安装哦
ip rule add fwmark 0x01/0x01 table 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -N SSUDP
iptables -t mangle -A SSUDP -d 127.0.0.0/24 -j RETURN
iptables -t mangle -A SSUDP -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A SSUDP -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A SSUDP -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A SSUDP -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A SSUDP -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A SSUDP -d xxx.xxx.xxx.xxx -j RETURN
iptables -t mangle -A SSUDP -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01
iptables -t mangle -A OUTPUT -j SSUDP
上面的xxx.xxx.xxx.xxx就是你Socks5服务器的地址
然后,我们启动redsocks2
redsocks2 -c ./red2.conf
由于mangle表只能修改prerouting链,所以我们无法在本机做测试,我们需要找到一台其他机器,将redsocks2程序所在服务器IP设置为默认网关,就可以测试了,如下我使用nslookup命令做DNS的测试
然后redsocks2的日志如下(如果没有日志说明前面iptables配置的有问题,如果有日志没有DNS结果说明Socks5服务器有问题或redsocks2配置有问题)