在Docker中安装ipsec-vpn过程记录(在Docker中安装ipsec-vpn过程记录)
使用hwdsl2/ipsec-vpn-server创建IPsec-VPN
docker pull hwdsl2/IPsec-vpn-server
创建环境变量文件
cat /opt/src/vpn.env
VPN_PUBLIC_IP=172.12.0.101
VPN_L2TP_NET=192.168.180.0/24
VPN_IPSEC_PSK=123.com
VPN_USER=vpnuser2
VPN_PASSWORD=123.com
启动IPsec VPN Server
docker run
--name ipsec-vpn-server
--env-file /opt/src/vpn.env
--restart=always
-p 500:500/udp
-p 4500:4500/udp
-d --privileged
hwdsl2/ipsec-vpn-server
采用这种方式启动时,实际上是在内部做了端口的映射:安装docker时,会生成一个bridge虚拟接口docker0, 地址为172.17.0.1, 而启动IPsec-vpn-server时,这个容器默认使用docker0,并在其上虚拟一个接口配置地址为172.17.0.2。 当宿主机收到发往UDP:500报文时,会替换为内部接口的地址172.17.0.2:500(如下所示,可通过iptables –nL看见具体的规则设定)
#宿主机docker0网桥接口
#宿主机上自动创建的500端口iptables规则
通过netstat可在宿主机上看见端口监听情况:
#宿主机的端口监听情况
启动后,可查看docker容器的执行状态(docker ps):
进入容器内部:
docker exec -it ipsec-vpn-server env TERM=xterm bash -l
#进入容器内命令行
执行ifconfig可见启动了两个接口,一个eth0(docker0这个桥接口成员之一), 另一个ppp作为L2TP拨号接入端口。在容器内执行netstat –anlp, 可见在eth0端口上监听了udp:500, udp:4500和udp:1701(L2TP)
#容器内的接口信息
但是在容器外面,我们看不到1701端口的监听,这是因为,一旦写上了IPsec隧道后,所有L2TP报文都会加密并封装成ESP报文,进入容器后才会解封送到容器eth0接口地址的1701的端口上。
win10终端拨入:
第一次使用win10终端拨入时,发现无法建立连接,抓包发现IPsec隧道已成功建立,但是无法进入L2TP的认证阶段,查找资料后,发现需要在Win10注册表中添加如下内容并重启
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesPolicyAgent]
"AssumeUDPEncapsulationContextOnSendRule"=dword:00000002
重启后,Win10终端终于正确拨入VPN Server
L2TP接口网络问题,导致终端不能上网
拨入后,Win10终端Ping VPN Server端的地址,发现ping 172.17.0.2可通(容器内部),但是ping 172.17.0.1不通(容器外部---宿主机)
检查,发现在Win10拨号建立的PPP端口,地址为192.168.42.10, 与我们环境配置文件所提供的VPN_L2TP_NET=192.168.180.0/24不符合,通过docker ps找到容器对应的CONTAINER ID(如:d5d1c438a8fc) , 然后执行:
docker stop d5d1c438a8fc #终止容器执行
docker rm d5d1c438a8fc #删除容器
去掉/opt/src/vpn.env中的VPN_L2TP_NET指定,再次运行容器。进入容器内部执行:
iptables –nL 检查防火墙规则:
#容器内的iptables规则
可见规则生效,win10拨入后,能正常访问外网。
查找根本原因是,在容器内的/opt/src/run.sh脚本中,虽然修改了/etc/ipsec.conf , 及防火墙规则修改,但是没有将对应的修改设置到/etc/xl2tpd/xl2tpd.conf, 如下图所示:
#容器内的xl2tpd.conf配置
方法一: 若确实需要修改L2TP_NET, 除了修改vpn.env文件外,还需要修改内部的/etc/xl2tpd/xl2tpd.conf配置文件。
方法二: 修改容器内的防火墙规则:
iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o eth0 -j MASQUERADE
iptables-save
容器内的虽有修改,需要保存到一个新Image中
docker commit 084bc4bdc5a0 ipsec-vpn-server:version4
下次启动时,使用新的image来启动:
docker run
--name ipsec-vpn-server
--env-file /opt/src/vpn.env
--restart=always
-p 500:500/udp
-p 4500:4500/udp
-d --privileged
ipsec-vpn-server:version4
Docker网络子系统支持以下网络驱动:
- bridge: 默认网络驱动,用于单宿主机的docker容器和主机通信;
- overlay:叠加网络,用于连接多个宿主机Docker进程管理的容器和swarm services;
- macvlan:将容器的虚拟网卡直接连接在主机所在的物理网络上;
- host:Docker 17.06 创建swarm services时支持,容器直接使用docker主机的网卡和网络;
- none:禁用容器的网络,不连接任何网络,swarm services不支持该类型;
- Network plugins:安装第三方网络插件,实现自定义的网络类型
单机安装时,只能看到三种类型(bridge, host, none)
docker network ls
# docker network ls
主机模式(host)
通过命令--network=host 指定,使用host模式的容器可以直接使用docker host的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
#主机模式
无网络模式(none)
这种网络模式下容器只有lo回环网络,没有其他网卡。none网络可以在容器创建时通过 --network=none 来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
桥接模式
容器的默认网络模式,docker在安装时会创建一个名为docker0的Linux bridge,在不指定--network的情况下,创建的容器都会默认挂到docker0上面。
#桥模式
创建一个容器之后一个新的网络接口被挂载到了docker0上,这个就是容器创建时创建的虚拟网卡。bridge模式为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,使容器之间,容器和docker host之间实现网络隔离。
主机模式启动ipsec-vpn
上面,我们用的是bridge模式启动的容器,现在修改为通过主机模式启动ipsec-vpn
删除已有容器后,通过如下命令重新创建并执行:
docker run
--name ipsec-vpn-server
--env-file /opt/src/vpn.env
--network=host
--restart=always
-d --privileged
hwdsl2/ipsec-vpn-server
此时,进入容器内部,我们通过ifconfig可看到,所有的接口信息与宿主机的接口信息一致。
碰见的问题:
Win10再次拨号l2tp-ipsec-vpn, 发现第一个报文就未响应。检查后发现,宿主机的防火墙接口未放开udp 500, 4500和1701端口
firewall-cmd --get-active-zone
internal
interfaces: ens4
external
interfaces: eth0
增加internal区域放开端口1701, 500, 4500
firewall-cmd --add-port=1701/udp --zone=internal –permanent
firewall-cmd --add-port=500/udp --zone=internal –permanent
firewall-cmd --add-port=4500/udp --zone=internal --permanent
firewall-cmd –reload
执行后再次检查端口开放情况:
firewall-cmd --list-ports --zone=internal
4500/udp 500/udp 1701/udp
Win10再次连接成功
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。