3
3
2019
16

使用 cgroups net_cls 来让 docker 走代理

本文来自依云'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 有可能会找不到模块的。(所以更新内核之后还是重启一下以避免尴尬吧。)

Category: shell | Tags: iptables linux cgroups 网络 代理 | Read Count: 140269
wweir 说:
Mar 03, 2019 09:28:06 AM

这问题也可以使用 sower 解决,直接架设个全局只能透明代理,无论在几层虚拟化下,都可以生效. 哈哈哈,成打广告的了.

项目地址: https://github.com/wweir/sower

wweir 说:
Mar 03, 2019 09:35:00 AM

有三点相比市面上的解决方案,很有吸引力:
1.智能规则,不需要自己不断添加新屏蔽的站点,也不会过度代理不必要的流量
2.流量隐蔽性比 shadowsocks 要高,一个是流量特征更少,另一个是不支持当前不安全的加密算法
3.配置起来简单. 要用其它东西实现全局透明代理,需要搭建一整套的几个服务,sower 把必要的东西都集成了,自身就是完整解决方案

Avatar_small
依云 说:
Mar 03, 2019 12:43:36 PM

看起来是提供了一整套预定义的方案,然而并不适合我:

* 我有自己的 DNS 方案。
* 此方案无法代理 git、ssh、mosh 等协议。
* 此方案会否干扰其它的访问?我并不需要一个系统全局的代理。
* 现有的服务不支持

fcying 说:
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"
```

Avatar_small
依云 说:
Mar 04, 2019 10:33:28 AM

哦,还能这样。不过我也没有这么一个 HTTP 代理呀。

JIN 说:
Mar 04, 2019 11:19:34 PM

socks5://127.0.0.1:7070 可以这样吧

Avatar_small
依云 说:
Mar 04, 2019 11:49:15 PM

咦这里支持 socks5 么?我去查查看。

Avatar_small
依云 说:
Mar 04, 2019 11:55:35 PM

文档没写,翻源码了,还真支持,并且只支持 socks5 这一种,不支持 socks4 和 socks5h 什么的。

hmgle 说:
Mar 06, 2019 08:08:08 PM

因 docker 是静态链接的,proxychains 没有办法让 docker 走代理。也可以使用 graftcp。不过因为 docker 网络请求都是通过运行在后台的 docker 进程发送的,所以把后台的 docker 停止掉,然后再用 graftcp 重新启动就可以啦。

https://i.imgur.com/QyBGUf2.gif

Avatar_small
依云 说:
Mar 06, 2019 10:59:28 PM

这个办法也不错。不过我最主要的是试试 net_cls 啦。
另外使用 ptrace 的话,有性能损失,更主要的是,我不能 strace 上去看看它在干什么了,不方便调试。

x b y 说:
Mar 21, 2019 08:36:00 PM

好厉害, 学习了一种新的代理方法。。。
我知道Dockerfile可以用代理,但是docker会把代理信息记录到image的history里,暴露给使用者。你这招似乎可以瞒天过海,非常方便啊。

hev 说:
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

Avatar_small
依云 说:
Mar 27, 2019 04:49:34 PM

是的,相当好用。我最近给 minecraft 用上了~

憨人 说:
Nov 20, 2019 05:42:28 PM

请问这么操作的效果是实现了容器内全局代理 还是容器内有了个443端口的http代理?

Avatar_small
依云 说:
Nov 20, 2019 07:31:20 PM

我没测过,不过容器内应该也是走代理的。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com