需要一台有公网IP的服务器
操作系统:Ubuntu 22.04 LTS
Docker版本:Docker Engine - Community 24.0.6
Docker镜像地址:https://hub.docker.com/r/kylemanna/openvpn
GitHub开源地址:https://github.com/kylemanna/docker-openvpn
服务端架设
生成配置文件
该Docker镜像对OpenVPN的一些操作进行了封装,这里初始化环境配置文件
# 初始化配置文件到宿主机的/opt/docker/openvpn目录下(可自行修改)
$ docker run -v /opt/docker/openvpn:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://公网IP
# 配置文件初始化完成,如有需要可以在这里修改配置文件便于后面生成证书
$ ls /opt/docker/openvpn/
ccd openvpn.conf ovpn_env.sh
生成服务端证书
OpenVPN中有证书的概念,服务端需要有证书才可以启动,否则会启动报错,这也是上面运行docker容器时为什么都加--rm
的原因,这里初始化服务端证书
# 根据配置文件初始化服务端证书,结尾nopass为可选项,表示无需密码生成证书,过程需要输入Common Name,如不想输入可以选择直接回车
$ docker run -v /opt/docker/openvpn:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki nopass
# 证书生成时间可能会比较长,会输出一堆.....+.......耐心等待即可,生成后可查看效果
$ ls /opt/docker/openvpn/
ccd openvpn.conf ovpn_env.sh pki
启动OpenVPN服务
启动OpenVPN服务就比较简单了,直接使用下面段命令启动容器即可,这里需要注意暴露端口使用的时udp协议,如果服务器有设置安全组记得要放行udp协议的1194端口
# 启动OpenVPN服务
$ docker run --name openvpn -v /opt/docker/openvpn:/etc/openvpn -p 1194:1194/udp --cap-add=NET_ADMIN -d kylemanna/openvpn
# 查看运行状态,检查OpenVPN是否启动成功
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85c5c0da569a kylemanna/openvpn "ovpn_run" 2 seconds ago Up 1 second 0.0.0.0:1194->1194/udp, :::1194->1194/udp openvpn
# 查看目录,发现此时多了一个crl.pem,据说是证书吊销列表文件,我没用过不太清楚不过不用管放着就行
$ ls /opt/docker/openvpn
ccd crl.pem openvpn.conf ovpn_env.sh pki
客户端管理
之前说过OpenVPN中有证书的概念,服务端必须有证书才可以启动,同样的客户端也需要有证书才能加入VPN网络,这里介绍Docker中封装的几个客户端管理命令,也可以点击这里直接看原文档
命令 | 解释 |
---|---|
docker exec -it openvpn easyrsa build-client-full [client] nopass | 生成无密码的客户端证书 |
docker exec -it openvpn ovpn_getclient [client] > [client].ovpn | 构建带有嵌入证书的.ovpn文件 |
docker exec -it openvpn ovpn_listclients | 查看客户端列表 |
docker exec -it openvpn ovpn_revokeclient [client] remove | 吊销客户端证书 |
使用案例
# 生成一个客户端证书 cc
$ docker exec -it openvpn easyrsa build-client-full cc nopass
# 查看客户端列表,多了一个刚刚创建的cc
$ docker exec -it openvpn ovpn_listclients
name,begin,end,status
cc,Nov 7 08:00:22 2023 GMT,Feb 9 08:00:22 2026 GMT,VALID
# 构建带有嵌入式证书的.ovpn文件
$ docker exec -it openvpn ovpn_getclient cc > cc.ovpn
# 查看配置文件目录,多个了cc.ovpn文件,这个就是客户端加入VPN网络用到的文件,里面嵌入了证书
$ ls /opt/docker/openvpn
ccd cc.ovpn crl.pem openvpn.conf ovpn_env.sh pki
# 正常来说每个客户端都应该有个独享的.ovpn证书,如果不想让某个人继续使用VPN就吊销它的证书,吊销过程需要手动输入yes
$ docker exec -it openvpn ovpn_revokeclient cc remove
# .ovpn文件需要手动删除,吊销后可以查看证书列表看看效果,这里我就不看了
$ rm /opt/docker/openvpn/cc.ovpn
当服务端的配置项做出修改后如果没有生效,建议删除证书重启容器后生成新的证书在进行测试
修改IP段
通过Docker镜像生成的环境配置中,默认使用的IP段是192.168.255.x
,如果不幸网络环境与这个IP段冲突就不好办了,针对这点可以通过修改配置文件来修改IP段,这里我选择将IP段修改为10.18.0.x
# 编辑OpenVPN配置文件
# 将 server 192.168.255.0 255.255.255.0 改为 server 10.18.0.0 255.255.255.0
# 将 route 192.168.254.0 255.255.255.0 改为 route 10.18.1.0 255.255.255.0
$ vim /opt/docker/openvpn/openvpn.conf
# 编辑环境配置文件
# 将 declare -x OVPN_ROUTES=([0]="192.168.254.0/24") 改为 declare -x OVPN_ROUTES=([0]="10.18.1.0/24")
# 将 declare -x OVPN_SERVER=192.168.255.0/24 改为 declare -x OVPN_SERVER=10.18.0.0/24
$ vim /opt/docker/openvpn/ovpn_env.sh
配置分割隧道
当客户端加入VPN网络后全局都会走VPN网络,如果服务器带宽不高就会严重影响使用体验,个人强烈推荐配置分割隧道,只有访问VPN内部资源时走VPN网络,可点击访问原文档查看对此的描述
# 禁用默认路由(-d),但仍使用NAT(-N)来保持网络地址转换启用
$ docker exec -it openvpn ovpn_genconfig -N -d
# 使用ovpn_genconfig修改配置后目录下会对原配置进行备份生成.bak文件
$ ls /opt/docker/openvpn
ccd crl.pem openvpn.conf openvpn.conf.1699346494.bak ovpn_env.sh ovpn_env.sh.1699346494.bak pki
配置静态(固定)IP
当客户端加入VPN网络后默认是从前往后分配IP地址的,如果有某台机器需要固定IP的话可以通过在ccd目录下添加配置文件来实现,可以点击这里查看原文档,例如之前创建的客户端,我希望使用cc证书登录的用户分配到的始终是静态IP
# 在ccd目录下创建与客户端同名的文件
# 在客户端同名文件中添加: ifconfig-push 10.18.0.6 10.18.0.5
# 其中.0.6代表IP地址,.0.5代表网关地址
$ vim /opt/docker/openvpn/ccd/cc
需要注意的是IP地址不能随便用,只能从以下范围中选取,具体详见这篇文章,否则可能会报错
[ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18]
[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38]
[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58]
[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78]
[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98]
[101,102] [105,106] [109,110] [113,114] [117,118]
[121,122] [125,126] [129,130] [133,134] [137,138]
[141,142] [145,146] [149,150] [153,154] [157,158]
[161,162] [165,166] [169,170] [173,174] [177,178]
[181,182] [185,186] [189,190] [193,194] [197,198]
[201,202] [205,206] [209,210] [213,214] [217,218]
[221,222] [225,226] [229,230] [233,234] [237,238]
[241,242] [245,246] [249,250] [253,254]
[1, 2]
IP地址默认被服务端占用,所以IP地址是从[5, 6]
开始分配的,个人建议按照OpenVPN的规范来使用,例如[21, 22]
这一组,应该用后面的22作为IP地址,前面的21作为网关,如下所示
# 假设这是ccd目录下某个配置文件
ifconfig-push 10.18.0.22 10.18.0.21
其他配置项
这里只记录几个我用到过的配置项,其余配置项日后我用到在随时补充
# 允许客户端与客户端相连接
client-to-client
# 允许一套证书或账户多人登录
duplicate-cn
Windows加入VPN网络
安装OpenVPN客户端软件,软件下载地址结尾会给出,安装过程中会提示安装虚拟网卡的弹窗,一定要点击同意,安装完成后打开OpenVPN的安装目录,将服务端构建的.ovpn文件下载并放入config目录下,然后双击运行OpenVPN软件,右下角右键建立连接即可
Linux加入VPN网络
这里使用Ubuntu作为演示机器,首先要保证服务器内有/dev/net/tun
设备文件,可以执行ls /dev/net/tun
命令查看,有打印结果就说明可以使用
Proxmox构建的CT虚拟机的特殊处理
如果使用Proxmox构建的CT虚拟机内没有该设备文件,需要检查宿主机是否有这个设备文件,如果宿主机有该设备文件但虚拟机内没有,可以编辑虚拟机的配置文件,具体如下所示
# 在宿主机内编辑CT虚拟机的配置文件
# 在配置文件结尾追加 lxc.mount.entry: /dev/net/tun dev/net/tun none bind,optional,create=file
# 然后回到CT虚拟机内重启系统,就可以看到这个设备文件了
$ vim /etc/pve/lxc/xxx.conf
Ubuntu加入VPN网络
在这之前需要先将.ovpn文件上传至ubuntu,假设文件上传至/root/client.ovpn
# 安装OpenVPN
$ apt install openvpn
# 加入VPN网络
$ openvpn --config /root/client.ovpn
异地组网没这么麻烦的,单纯实现异地组网可以用tailscale。看了你的网站很受益,希望能加友链https://3141635mi0.goho.co/
第一次听说tailscale涨知识了,友链已加,话说你这个域名挺随意的....
花生壳的二级域名,网站都是跑在arm32位的CPU上的