利用iptables实现docker网关路由及内网服务端口映射

总感觉使用docker时坑坑洼洼的,有时不留神duang的一声就掉坑里了。docker自带的网络用起来一直感觉不是太方便,比如启动一个需要访问容器内部端口的容器时只要用-v参数做端口映射,这时docker会启用一个类似这样的进程来完成端口转发的功能:

1
2
$ docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5000 -container-ip 172.17.0.6 -container-port 5000
$

看似很美好,从外面可以访问容器内部端口。不过有两个问题需要解决:
1、如果由于某些特别的要求需要再新增加一个端口映射,怎么办。
2、此时容器内部是不能访问外网(公网),容器内的程序不能解析域名或者从公网获取数据等。
第1个问题,可以新建容器,在新建容器的时候映射多个端口。但是之前的容器还是只有一个端口映射,看似问题解决了,其实并没有解决。这2个问题都可以通过强大的iptables来解决,不用新建或重启容器只需要插入几条规则即可。
针对单台宿主机(多台宿主机集群不用考虑):
docker宿主机网卡eth1(外网)ip:222.7x.1xx.xx9/24,网关:222.7x.1xx.1
docker宿主机网卡eth0(内网)绑定到自定义的网桥br0,ip:10.0.1.10/24,网关:无
宿主机网卡配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BRIDGE=br0
HWADDR=00:0C:29:08:63:C5
$ cat /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
BOOTPROTO=static
ONBOOT=yes
TYPE=Bridge
IPADDR=10.0.1.10
NETMASK=255.255.255.0
$ cat /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=static
HWADDR=00:0C:29:08:63:CF
ONBOOT=yes
TYPE=Ethernet
IPADDR=222.7x.1xx.xx9
NETMASK=255.255.255.0
GATEWAY=222.7x.1xx.1
[root@h5-dev1 ~]#

重启网络服务,修改docker配置文件/etc/sysconfig/docker centos6.6),让docker使用自定义网桥br0(也可以不用自定义的网桥,这里使用自定义网桥主要是为了和其它宿主机上的容器互通)。

1
2
other_args="-b br0"
#other_args=

网络环境基本就是这样的了,现在开始主题-修改iptables(采用脚本的方式,方便快捷)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
iptables -F
iptables -t nat -F
modprobe ip_conntrack_ftp

#### Below are the basal iptables config, normally need not be modified #######
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p tcp --source-port 53 -j ACCEPT
iptables -A INPUT -p udp --source-port 53 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT

##### Below are the Appalication related iptables config #######
#设置内网路由转发到外网
iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE
#端口映射,将内网服务映射到外网
iptables -t nat -I PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.1.2:80
iptables -t nat -I PREROUTING -p tcp --dport 873 -j DNAT --to 10.0.1.2:873
iptables -t nat -I PREROUTING -p tcp --dport 90022 -j DNAT --to 10.0.1.2:22
iptables -t nat -I PREROUTING -p tcp --dport 90023 -j DNAT --to 10.0.1.3:22
iptables -t nat -I PREROUTING -p tcp --dport 3306 -j DNAT --to 10.0.1.3:63306

iptables -A INPUT -j DROP
#iptables -A FORWARD -j DROP

执行这个设置iptables设置的脚本,容器内部就能访问外网的数据了,除了在创建容器的时候用-v参数做端口映射外,还可以在该脚本中增加新的端口映射。

----------------本文结束 感谢阅读----------------