前言
最近要搞个公司内网穿透类似的东东,需要从外网连接到办公内网,一波挑选之后决定采用 OpenVPN。由于需要搭一个大内网,且不妨碍访问外网,并且要求客户端之间也要互通,搜了一下网上都没有 docker 版本的说明,倒腾两天,记录一下。
机器配置
机器:
- 服务端 CentOS 7.3
- 客户端 Windows 10/Ubuntu Server 16.04
其实是什么平台都不重要,因为全篇都在 docker 下玩的
Git 项目:
安装Docker,拉取镜像
sudo yum -y install docker.io
docker pull kylemanna/openvpn
配置OpenVPN
- 配置数据卷,生成配置文件。预计网段人数不多,使用192.168.0.0/24网段,但需要注意的是在配置固定IP时,掩码必须为/30,因此固定IP需要注意正确配置。
#配置数据卷
export OVPN_DATA=openvpn-data
docker volume create --name $OVPN_DATA
#生成配置文件
#-d 取消默认配置 -c 打开c2c模式 -u 指定当前IP
#-s 划分服务器子网 -C 指定算法
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -d -c -C 'AES-256-CBC' -u udp://SERVER_IP -s 192.168.100.0/24
- 生成密钥文件,输入密钥和CA名称
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
- 运行容器
#开启特权
docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:1194/udp --restart=on-failure:10 --cap-add=NET_ADMIN --name=openvpn --privileged=true kylemanna/openvpn
#登陆docker
docker run -v $OVPN_DATA:/etc/openvpn -it --rm kylemanna/openvpn bash -l
用户操作
添加用户
- 生成证书
#生成客户端证书,输入密钥
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
#需要配置密码则删掉nopass
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full testuser
- 导出证书
#将用户证书导出到本地文件
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient testuser > testuser.ovpn
- 如果有需要,需要给某个用户生成固定ip,操作如下:
//注意掩码为/30,配置固定IP需要保证其可用
echo "ifconfig-push 192.168.100.5 192.168.100.6" > /var/lib/docker/volumes/"$OVPN_DATA"/_data/ccd/client1
删除用户
//删除用户证书
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa revoke user
//更新证书数据库
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa gen-crl update-db
//重启openvpn容器
docker restart openvpn
客户端下载及安装
Windows
下载对应客户端后,在系统上安装 OpenVPN 客户端软件,将导出的文件 xx.ovpn 放到 OpenVPN 的配置文件夹中,默认是C:\Program Files\OpenVPN\config。或者直接打开 OpenVPN 客户端,右键-导入配置文件。
运行 OpenVPN 客户端软件,连接即可
Linux
Linux更为简单:
#先安装openvpn
sudo apt install openvpn
#配置.ovpn为配置文件
openvpn --config xxx.ovpn
增删用户脚本
为了减少工作量,方便快速配置,可以使用如下两个增添用户的脚本。
OpenVPN 创建用户脚本:
#!/bin/bash
read -p "please your username: " NAME
OVPN_DATA="openvpn-data"
LOCALIP="IP"
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full $NAME nopass
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient $NAME > /data/openvpn/conf/"$NAME".ovpn
#修改端口(可选)
sed -i "s/$LOCALIP 1194/$LOCALIP 1194/g" /data/openvpn/conf/"$NAME".ovpn
#压缩(可选)
echo "comp-lzo" >> /data/openvpn/conf/"$NAME".ovpn
docker restart openvpn
echo "CA saved to /data/openvpn/conf/$NAME.ovpn"
OpenVPN 删除用户脚本:
#!/bin/bash
read -p "Delete username: " DNAME
OVPN_DATA="openvpn-data"
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa revoke $DNAME
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa gen-crl
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/reqs/"$DNAME".req
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/private/"$DNAME".key
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/issued/"$DNAME".crt
#删除相关用户conf(可选)
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn rm -f /data/openvpn/conf/"$DNAME"
docker restart openvpn
echo "Deleted $DNAME"
验证
docker pull 一个Nginx,连接VPN服务器,先 ping ,互相 curl。
systemd持久化
目的:自动下载最新的 docker-openvpn
镜像并更新;如果服务挂掉, systemd 可以设定为每隔10秒进行重启。
设定 volume
OVPN_DATA="openvpn-data" docker volume create --name $OVPN_DATA
初始化容器
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
下载 docker-openvpn@.service 放到
/etc/systemd/system
,根据实际情况修改curl -L https://raw.githubusercontent.com/kylemanna/docker-openvpn/master/init/docker-openvpn%40.service | sudo tee /etc/systemd/system/docker-openvpn@.service
设定开机启动
systemctl enable --now docker-openvpn@example.service
验证一下
systemctl status docker-openvpn@example.service journalctl --unit docker-openvpn@example.service
错误记录
连接时发生
write to TUN/TAP : Invalid argument (code=22)
服务端启用了
comp-lzo
,但生成的客户端 ovpn 文件没有,添加comp-lzo
到 *.ovpn即可连接时报 Warning:
WARNING: this cipher's block size is less than 128 bit (64 bit). Consider using a --cipher with a larger block size.
进入容器看看支持哪些算法:
openvpn --show-ciphers
,挑一个在 genconfig 的时候使用-C
参数进行配置:docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -C $CIPHER
高级安全
备份
安全高要求下可以离线备份,本场景不需要。
# 备份到存档
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn tar -cvf - -C /etc openvpn | xz > openvpn-backup.tar.xz
# 恢复到新数据卷
docker volume create --name $OVPN_DATA
xzcat openvpn-backup.tar.xz | docker run -v $OVPN_DATA:/etc/openvpn -i kylemanna/openvpn tar -xvf - -C /etc
CA root key安全
本场景无需如此,先做记录。ovpn_copy_server_files 脚本将所有需要的配置放在默认的子目录中 $OPENVPN/server
docker run --net=none --rm -t -i -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
docker run --net=none --rm -t -i -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_initpki
docker run --net=none --rm -t -i -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_copy_server_files
其它记录
以下为记录,并未操作
防火墙配置
可选操作。
关闭firewalld
systemctl stop firewalld.service
systemctl disable firewalld.service
装iptables
yum -y install iptables-services net-tools
systemctl enable iptables.service
配置iptables
iptables -A Filter -d 127.0.0.1 -j ACCEPT
iptables -A Filter -p tcp --dport 80 -j ACCEPT
iptables -A Filter -j DROP
iptables -A INPUT -p tcp --destination-port 1194 -j ACCEPT
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.85.0/24 -j SNAT --to-source 10.10.10.167
docker-compose
如果喜欢 docker-compose ,可以使用如下文件部署:
version: '2'
services:
openvnp:
cap_add:
- NET_ADMIN
image: kylemanna/openvpn
container_name: openvpn
ports:
- "1194:1194/udp"
restart: always
volumes:
- ./openvpn-data/conf:/etc/openvpn
相关操作:
docker-compose run --rm openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
docker-compose run --rm openvpn ovpn_initpki
docker-compose run --rm openvpn rm /etc/openvpn/ovpn_env.sh
docker-compose run --rm openvpn ovpn_genconfig -N -d -n 192.168.13.6 -u udp://vpn.mycompany.net -p "dhcp-option DOMAIN mycompany.net" -p "route 192.168.13.0 255.255.255.0" -p "route 172.17.0.0 255.255.0.0"