0%

通过IPTABLES转发docker流量

本文研究了将docker流量代理到内网中。

一、背景

在一个项目中,利用docker实现了扫描器,但是在扫描内网时,如果将整个容器部署到内网中就太蠢了。所以想通过代理的方式进行。但是当初设计扫描器的时候,没有考虑到内网代理问题,所以打算将docker流量全部代理到内网中。

二、前置知识

本文研究中,实现该需求存在三种办法。需要一些其他的知识。

2.1、REDSOCKS

工具连接:https://github.com/darkk/redsocks

This tool allows you to redirect any TCP connection to SOCKS or HTTPS proxy using your firewall, so redirection may be system-wide or network-wide.

这个工具可以通过iptables将所有TCP流量转至它监听的端口下,然后通过代理发出。

https://www.notion.so/REDSOCKS-fb75b0b02b9d4e87867771166ee43731

2.2、DOCKER网络

在docker网络中,存在以下情况:

  • host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
  • Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
  • None:该模式关闭了容器的网络功能。
  • Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。

本实验中主要需要认识三种模式: hostcontainerbridge 。三种模式分别应对三种方法。

2.3、端口转发

端口转发选的是 ew

1
./ew_for_linux64 -s ssocksd -l 44444

2.4、IPTABLES

关于 IPTABLSE 的基础内容为:https://www.notion.so/IPTABLES-fce85f3fd64641d1860600801e734cc1

首先要弄明白docker流量在iptables下的流向问题。在docker容器内:curl www.baidu.com

DOCKER容器内:OUTPUT → POSTROUTING → 宿主机内:PREROUTING → FORWARD → POSTROUTING

三、通过 docker host

3.1、原理

让将宿主机系统所有的流量走代理,然后让docker使用 host 模式。然后docker 容器的流量就走了代理。

3.2、配置

redsocks配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
base {
log_debug = off;
log_info = on;
log = "file:/tmp/red.log";
daemon = on;
user = redsocks;
group = redsocks;
redirector = iptables;
}
redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = <vps_ip>;
port = 44444;
type = socks5;
}

iptables配置

1
2
3
4
5
6
7
8
9
10
11
12
iptables -t nat -N REDSOCKS # 在nat下新增一个链
iptables -t nat -A REDSOCKS -d <vps> -j RETURN
iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345
iptables -t nat -A OUTPUT -p tcp -j REDSOCKS

docker启动

1
docker run --net=host --rm -it --name t3 myubuntu curl www.baidu.com

四、通过 docker container

4.1、原理

新增一个容器,在这个容器中设置代理相关内容(通过redsocks)。然后将其他容器的网络使用这个容器的网络(和上面方案很像)。

4.2、配置

基础的docker镜像

1
2
3
4
FROM ubuntu:16.04
COPY ./sources.list /etc/apt/sources.list # 换个源
RUN apt-get update && apt install -y curl && apt install -y iputils-ping && apt install -y vim
CMD sleep 60000

redsocks代理镜像

Dockerfile

1
2
3
4
5
FROM myubuntu
RUN apt install -y redsocks && apt install -y iptables
COPY ./redsocks.conf /etc/redsocks.conf
COPY ./red_iptables.sh /red_iptables.sh
CMD /red_iptables.sh

redsocks.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
base {
log_debug = off;
log_info = on;
log = "file:/tmp/red.log";
daemon = off; # 需要修改为off
user = redsocks;
group = redsocks;
redirector = iptables;
}
redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = <vps_ip>;
port = 44444;
type = socks5;
}

red_iptables.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
iptables -t nat -N REDSOCKS # 在nat下新增一个链
# 忽略宿主机和vps的地址
iptables -t nat -A REDSOCKS -d <vps_ip> -j RETURN
# 忽略本地地址
iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
# 其余tcp包都转发到redsocks端口
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345 # <redsocket监听的本地端口>
iptables -t nat -A OUTPUT -p tcp -j REDSOCKS
/usr/sbin/redsocks -c /etc/redsocks.conf

启动redsocks镜像

1
docker run --privileged --rm -d --name r1 redc

启动需要做转发的镜像

1
docker run --network="container:r1" --rm --name -d t3 myubuntu

测试

1
docker exec -it t3 curl www.baidu.com

镜像情况png

container网络png

五、通过 docker bridge

5.1、原理

在2.4节中提到了在bridge下,docker流量的转发情况

DOCKER容器内:OUTPUT → POSTROUTING → 宿主机内:PREROUTING → FORWARD → POSTROUTING

为了将全部的流量转发到redsocks中,只能在PREROUTING下处理。

5.2、配置

重要

在主机配置好redsocks等内容。这里有个要注意的地方,redsocsk中监听的IP要改为 0.0.0.0 。(可能是因为在PREROUTING的时候,这属于非本机的流量,如果redsocks监听 127.0.0.1 则不能转发外部流量。)

按照第三章节中配置好主机信息。然后使用下面命令进行docker流量转发。

1
iptables -t nat -I PREROUTING -i docker0 -j REDSOCKS

5.3、测试

转发前

转发前png

转发后

转发后png

六、讨论

在进行扫描时,一是可以考虑在扫描器内集成代理的功能。但是,如果我们需要调度很多模块(再调度其他开源项目),这么做可能会很复杂。所以可以考虑将docker容器本身的流量进行转发。

在转发此流量的过程中,本次提出3种不同情况的方法,三种办法对应了三种docker的网络模型。所以他们也会受到DOCKER网络本身的限制。

例如在host网络中,所有的端口等信息将会使用主机本身的内容。

By o1hy : blog.o1hy.com