本文来自依云's Blog,转载请注明。
我这里 docker hub 连不上或者连上了访问很慢,根本没法用。本来我常规代理的办法,要么是 proxychains,要么是用 iptables 代理特定的 IP 段。至于 docker 嘛,亚马逊的 IP 段那么多,它用到的域名我也不是很清楚,一点点加好麻烦。作为系统服务,用 proxychains 不仅得修改 systemd 服务配置,而且不知道会不会出什么幺蛾子。最近刚好在某个地方看到这一手,就试试啰。
其实用法很简单的。去 /sys/fs/cgroup/net_cls 下建立个目录,往 net_cls.classid 里写一个整数(支持十六进制的 0x 表示法),然后把 dockerd 的 pid 写到 cgroup.procs 里去。最后用 iptables 代理这部分流量即可。现在都用 443 端口啦,所以只要代理它便好,也避免影响了别的东西:
iptables -t nat -A OUTPUT -p tcp --dport 443 -m cgroup --cgroup 0x110001 -j REDIRECT --to-ports XXX
XXX 是 ss-redir 的端口啦。
注意不要把进程的 pid 往 tasks 文件里写。那里得写的是 task 的 id 而不是 process 的 id,也就是说(用内核的术语来说)是线程的 pid 而不是进程的 tgid(thread group id)。所以非要写 tasks 文件的话,得把 docker 所有的线程的 pid 都写进去才行。真是混乱呢……画个表格好了:
用户态 | 内核 | 相关系统调用 |
---|---|---|
pid | tgid | getpid, kill |
tid | pid | gettid, tgkill |
process | task group | fork, clone without CLONE_THREAD |
thread | task | clone with CLONE_THREAD |
另外如果更新过内核的话,那句 iptables 有可能会找不到模块的。(所以更新内核之后还是重启一下以避免尴尬吧。)
Mar 03, 2019 09:28:06 AM
这问题也可以使用 sower 解决,直接架设个全局只能透明代理,无论在几层虚拟化下,都可以生效. 哈哈哈,成打广告的了.
项目地址: https://github.com/wweir/sower
Mar 03, 2019 09:35:00 AM
有三点相比市面上的解决方案,很有吸引力:
1.智能规则,不需要自己不断添加新屏蔽的站点,也不会过度代理不必要的流量
2.流量隐蔽性比 shadowsocks 要高,一个是流量特征更少,另一个是不支持当前不安全的加密算法
3.配置起来简单. 要用其它东西实现全局透明代理,需要搭建一整套的几个服务,sower 把必要的东西都集成了,自身就是完整解决方案
Mar 03, 2019 12:43:36 PM
看起来是提供了一整套预定义的方案,然而并不适合我:
* 我有自己的 DNS 方案。
* 此方案无法代理 git、ssh、mosh 等协议。
* 此方案会否干扰其它的访问?我并不需要一个系统全局的代理。
* 现有的服务不支持
Mar 04, 2019 10:18:06 AM
直接修改docker配置, 让他全局走代理不就好了
```
vim /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:4411/" "NO_PROXY=localhost,127.0.0.1"
```
Mar 04, 2019 10:33:28 AM
哦,还能这样。不过我也没有这么一个 HTTP 代理呀。
Mar 04, 2019 11:19:34 PM
socks5://127.0.0.1:7070 可以这样吧
Mar 04, 2019 11:49:15 PM
咦这里支持 socks5 么?我去查查看。
Mar 04, 2019 11:55:35 PM
文档没写,翻源码了,还真支持,并且只支持 socks5 这一种,不支持 socks4 和 socks5h 什么的。
Mar 05, 2019 07:08:15 AM
嗯,谢谢 :)
Mar 06, 2019 08:08:08 PM
因 docker 是静态链接的,proxychains 没有办法让 docker 走代理。也可以使用 graftcp。不过因为 docker 网络请求都是通过运行在后台的 docker 进程发送的,所以把后台的 docker 停止掉,然后再用 graftcp 重新启动就可以啦。
https://i.imgur.com/QyBGUf2.gif
Mar 06, 2019 10:59:28 PM
这个办法也不错。不过我最主要的是试试 net_cls 啦。
另外使用 ptrace 的话,有性能损失,更主要的是,我不能 strace 上去看看它在干什么了,不方便调试。
Mar 21, 2019 08:36:00 PM
好厉害, 学习了一种新的代理方法。。。
我知道Dockerfile可以用代理,但是docker会把代理信息记录到image的history里,暴露给使用者。你这招似乎可以瞒天过海,非常方便啊。
Mar 27, 2019 09:27:50 AM
哈哈,从基于ptrace的TCP重定向项目转到了这里,从功能和实现复杂度来看,还是用cgroup net_cls更简单、灵活,也通用。
将进程pid(tgid)写入cgroup tasks意味着当前进程的所有线程都会被匹配被重定向吧。
我用同样的方法来实现类似proxychains的前辍命令给chroot的子系统全局代理是直接施加到chroot进程上的,它fork出的所有子进程都会在group中。
实现方法:https://hev.cc/2813.html
Mar 27, 2019 04:49:34 PM
是的,相当好用。我最近给 minecraft 用上了~
Nov 20, 2019 05:42:28 PM
请问这么操作的效果是实现了容器内全局代理 还是容器内有了个443端口的http代理?
Nov 20, 2019 07:31:20 PM
我没测过,不过容器内应该也是走代理的。