当前位置: 首页 > 科技观察

终端程序不支持SOCKS5-HTTP代理怎么办?有了这神器,你终于可以跨山跨海了!

时间:2023-03-18 13:28:25 科技观察

你是不是经常需要通过终端下的一些实用程序来工作,比如:Git等,但是由于这些终端程序默认不支持Socks5代理或者HTTP代理,访问的时候速度可能会很慢一些需要科学上网的网络服务。通常我们的解决方法是使用环境变量exportALL_PROXY=socks5://proxyAddress:port或exporthttp_proxy=http://proxyAddress:port为所有终端程序配置全局代理。这虽然有效,但并不是最好的解决办法。今天给大家介绍一个神器graftcp,graftcp可以将任意指定终端程序的TCP连接重定向到SOCKS5或者HTTP代理,而不影响其他终端程序。有没有很好的解决你的痛点?简介graftcp可以将任何指定程序(应用程序、脚本、shell等)的TCP连接重定向到SOCKS5或HTTP代理。与tsocks、proxychains或proxychains-ng相比,graftcp没有使用LD_PRELOAD技术劫持共享库的connect()、getaddrinfo()等系列函数来达到重定向的目的。该方法只对使用动态链接编译的程序有效。对于静态链接编译的程序,比如默认选项编译的Go程序,proxychains-ng无效。graftcp使用ptrace(2)系统调用来跟踪或修改任何指定程序的连接信息,对任何程序都有效。工作原理将在后面解释。项目地址:https://github.com/hmgle/graftcp安装graftcp在Linux系统中运行。graftcp-local是用Go写的,需要Go环境。$gitclonehttps://github.com/hmgle/graftcp.git$cdgraftcp$makemake执行后,可以运行graftcp-local/graftcp-local和./graftcp。您也可以将它们全部安装到系统中:在$sudomakeinstall之后,graftcp-local将在系统启动时自动运行。使用方法参数graftcp-local:$graftcp-local/graftcp-local-hUsageofgraftcp-local/graftcp-local:-configstringPathtotheconfigurationfile-http_proxystringhttpproxyaddress,e.g.:127.0.0.1:8080-listenstringListenaddress(default":2233")-logfilestringWritelogstofile-0loglevelValueLogstofile-6)(default1)-pipepathstringPipepathforgraftcptosendaddressinfo(default"/tmp/graftcplocal.fifo")-select_proxy_modestringSetthemodeforselectaproxy[auto|random|only_http_proxy|only_socks5](default"auto")-servicestringControlthesystemservice:["start""stop""restart""install""uninstall"]-socks5stringSOCKS5address(default"127.0.0.1:1080")-syslogSendlogstothelocalsystemlogger(EventlogonWindows,syslogonUnix)graftcp:$graftcp-hUsage:graftcp[options]prog[prog-args]Options:-a--local-addr=graftcp-local'sIPaddress.Default:localhost-p--local-port=Whichportisgraftcp-locallistening?Default:2233-f--local-fifo=Pathoffifotocommunicatewithgraftcp-local.Default:/tmp/graftcplocal.fifo-b--blackip-file=TheIPinblack-ip-filewillconnectdirect-w--whiteip-file=Onlyredirecttheconnectthatdestinationipinthewhite-ip-filetoSOCKS5-n--not-ignore-localConnectingtolocalisnotchangedbydefault,thisoptionwillredirectittoSOCKS5-h--helpDisplaythishelpandexit使用示例假定您正在运行默认地址“localhost:1080”上的SOCKS5代理,首先启动graftcp-local:$graftcp-local/graftcp-local通过graftcp从golang.org安装Go包:$./graftcpgoget-vgolang.org/x/net/proxyviagraftcp打开Chromium/Chrome/Firefox浏览器,所有的网页请求都会被重定向到SOCKS5代理:$./graftcpchromium-browser通过graftcp启动Bash/Zsh/Fish,在这个新打开的shell中执行的任何新命令都会生成TCP连接将被重定向到SOCKS5代理:%./graftcpbash$wgethttps://www.google.com工作原理是为了达到将一个app发起的TCP连接重定向到其他目标地址的目的,而app本身并没有意识到这一点,大概需要这些条件:fork(2)一个新进程,使用execve(2)启动应用程序,并使用ptrace(2)在app执行每一次TCP连接前跟踪、捕获并拦截connect(2)系统调用,获取目标地址的参数,将pipeline传递给graftcp-local修改connect(2)系统调用的目标address参数是graftcp-local的地址,然后继续执行中断的系统调用。返回成功后,程序认为连接的是原地址,实际上连接的是graftcp-local地址。这叫“移栽花木”。graftcp-local根据连接信息和目标地址信息与SOCKS5代理建立连接,将app请求的数据重定向到SOCKS5代理。这里可能会有一个疑问:既然任何系统调用的参数都是可以修改的,那么通过修改write(2)/send(2)的参数,直接把原来的目标地址信息追加到buffer中不是更简单吗?该应用程序到graftcp-local?答案是做不到。如果直接向子进程中运行的被跟踪程序的缓冲区添加信息,可能会造成缓冲区溢出,导致程序崩溃或覆盖其他数据。另外execve(2)会将所有的共享内存分离出来,所以被跟踪app的writebuffer不能通过共享内存携带更多的数据,所以这里使用pipeline将原来的目标地址信息传递给graftcp-local。简单的过程如下:+----------------++--------++--------++------+|graftcp|desthost|||||||(追踪器)+---PIPE----->|||||||^|info|||||||ptrace||||||||v||||||||+------+||||||||||连接||连接||连接|||+-------------->|graftcp+-------->|SOCKS5+------>|dest||||||-local||or||host|||app||req||req|HTTP|req||||(tracee)+------------->|+--------->|代理+-------->|||||||||||||||resp||resp||resp|||||<----------------+|<--------+|<--------+||+--------+||||||+-----------------++--------++--------++------+什么是常见问题解答和提示如何重定向TCP连接?主要有:全局类型、设置环境变量类型和只针对程序(或进程)类型。全局:比如使用iptables+RedSocks可以将满足一定规则的系统流量转换成SOCKS5流量。这种方法的优点是全局有效;缺点是所有符合规则的流量都会被重定向,影响范围比较大。如何设置环境变量:有些程序在启动的时候会读取代理相关的环境变量来决定是否将自己的数据转换成代理协议对应的流量。例如curl会读取http_proxy、ftp_proxy、all_proxy环境变量,根据请求方案决定将流量转换到哪个代理。这种方法只有在程序本身实现转换功能的情况下才有效,局限性比较大。Program-only模式:该模式只对特定程序执行重定向,例如tsocks或proxychains。前面说了,它们都是之前使用LD_PRELOAD劫持动态库实现的,对于Go等使用默认静态链接编译的程序是无效的。graftcp对此进行了改进,能够重定向任何程序的TCP连接。如果应用程序连接到本地计算机,使用graftcp是否会将连接重定向到SOCKS5代理?惯于。默认情况下,目标地址为本地的连接将被忽略。如果要重定向所有地址,可以使用-n选项。如果要忽略更多地址,可以将它们添加到黑名单IP文件中;如果只想重定向某些IP地址,可以将这些地址添加到白名单IP文件中。使用graftcp--help设置参数。我的DNS请求被污染了,graftcp会处理DNS请求吗?惯于。graftcp目前只处理TCP连接。推荐使用dnscrypt-proxy或ChinaDNS解决DNS污染问题。clone(2)参数有一个名为CLONE_UNTRACED的标志,可以防止父进程跟踪自己。graftcp是如何实现强制跟踪的?graftcp会在调用clone(2)之前拦截子进程并清除CLONE_UNTRACED标志位,所以被跟踪的子进程最终会逃脱被跟踪的命运。另外,这个CLONE_UNTRACED标志是给内核使用的,普通程序不应该设置它。Linux提供了一种限制被ptrace(2)跟踪的方法:设置/proc/sys/kernel/yama/ptrace_scope的值,如果ptrace(2)失败,请检查该值是否被修改。支持macOS吗?不,用于macOS的ptrace(2)是一个半生不熟的产品。不过理论上也可以参考DTrace实现,见issue12。或许有兴趣的同学可以趟过这趟浑水。