OpenConnect VPN¶
Kubernetes是Google开发的容器编排系统,当你开始学习和测试Kubernetes时候,你会发现,很多基于Google的软件仓库无法访问,会给你的学习和工作带来极大的困扰。
OpenConnect VPN Server,也称为 ocserv
,采用OpenConnect SSL VPN协议,并且和Cisco AnyConnect SSL VPN协议的客户端兼容。目前不仅加密安全性好,而且客户端可以跨平台,主流操作系统以及手机操作系统都可以使用。
备注
如果你使用Google的软件仓库来安装最新版本的Kubernetes,并按照Google的文档进行实践,需要一个科学上网的梯子来帮助你。
准备工作:
需要购买一台海外VPS
需要一个域名,在注册域名中添加一条记录指向新购买VPS的IP地址
备注
使用Let’s Encrypt签发的证书是针对域名的,所以不仅需要购买VPS,还需要提前准备好域名。
部署OpenConnect VPN Server¶
安装ocserv:
apt install ocserv
安装完成后,OpenConnect VPN服务自动启动,可以通过 systemctl status ocserv
检查。
源代码编译¶
在 Arch Linux 上安装 ocserv
比较麻烦一些,需要通过 Arch Linux AUR 编译安装,也就是先安装 yay
,然后执行 yay -S ocserv
,不过在2023年11月的尝试安装失败,原因是 ocserv 依赖的 freeradius-client
(AUR) 引用了一个已经不再维护的 libpcl
,所以直接安装会失败。所以我实际安装是通过源代码编译安装的:
wget https://gitlab.com/openconnect/ocserv/-/archive/1.2.2/ocserv-1.2.2.tar.gz
tar xfz ocserv-1.2.2.tar.gz
cd ocserv-1.2.2
./autogen.sh
./configure && make && sudo make install
# 方便采用ubuntu的启动配置文件
ln -s /usr/local/sbin/ocserv /usr/sbin/ocserv
服务起停配置文件我采用了 Ubuntu Linux 提供的 Systemd进程管理器 配置:
/lib/systemd/system/ocserv.service
:
[Unit]
Description=OpenConnect SSL VPN server
Documentation=man:ocserv(8)
After=network-online.target
After=dbus.service
[Service]
PrivateTmp=true
PIDFile=/run/ocserv.pid
ExecStart=/usr/sbin/ocserv --foreground --pid-file /run/ocserv.pid --config /etc/ocserv/ocserv.conf
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
创建
/etc/ocserv/ocserv.conf
(从 Ubuntu Linux 发行版默认配置提取):
# 以下行注释关闭使用系统账号登陆
# auth = "pam[gid-min=1000]"
# 添加以下行表示独立密码文件认证
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
# 只开启TCP端口,关闭UDP端口,以便使用BBR加速
tcp-port = 443
# udp-port = 443
# 修改证书,注释前两行,添加后两行,表示使用Let's Encrypt服务器证书
# server-cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
# server-key = /etc/ssl/private/ssl-cert-snakeoil.key
server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem
# 设置客户端最大连接数量,默认是16
max-clients = 16
# 每个用户并发设备数量
max-same-clients = 2
# 启用MTU discovery以提高性能
#try-mtu-discovery = false
try-mtu-discovery = true
# 设置默认域名为vpn.example.com
default-domain = vpn.example.com
# 修改IPv4网段配置,注意不要和本地的IP网段重合
ipv4-network = 10.10.10.0
# 将所有DNS查询都通过VPN(防止受到DNS污染)
tunnel-all-dns = true
# 设置使用Google的公共DNS
dns = 8.8.8.8
# 注释掉所有路由参数
# route = 10.10.10.0/255.255.255.0
# route = 192.168.0.0/255.255.0.0
# route = fef4:db8:1000:1001::/64
# no-route = 192.168.5.0/255.255.255.0
备注
Arch Linux 仓库提供软件包上述配置文件可能已经就绪(不过我尚未实践 Arch Linux AUR 安装成功)
配置¶
安装Let’s Encrypt客户端(Certbot):
sudo apt install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt update sudo apt install certbot
警告
本文使用了 example.com
作为案例域名,实际操作时,请使用你自己的正确域名
确保80端口nginx服务暂停,然后从Let’s Encrypt获取一个TLS证书:
sudo certbot certonly --standalone --preferred-challenges http --agree-tos --email admin@example.com -d vpn.exapmle.com
备注
在执行上述 certbot
命令获取证书前,需要暂停80端口的nginx服务,因为 certbot
会监听该端口来迎接Let’s Encrypt验证域名 vpn.example.com
(也就是你执行生成证书的服务器): --preferred-challenges http ... -d vpn.exapmle.com
否则会报错:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for vpn.example.com
Cleaning up challenges
Problem binding to port 80: Could not bind to IPv4 or IPv6.
一切正常的话,会收到如下正确获得并存储证书的信息:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for vpn.example.com
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/vpn.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/vpn.example.com/privkey.pem
Your cert will expire on 2023-04-14. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
警告
Let’s Encrypt提供的证书有效期3个月,所以每3个月需要使用上述命令重新生成一次证书。建议 使用cron定时更新letsencrypt证书
修改ocserv配置文件
/etc/ocserv/ocserv.conf
:
# 以下行注释关闭使用系统账号登陆
# auth = "pam[gid-min=1000]"
# 添加以下行表示独立密码文件认证
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
# 只开启TCP端口,关闭UDP端口,以便使用BBR加速
tcp-port = 443
# udp-port = 443
# 修改证书,注释前两行,添加后两行,表示使用Let's Encrypt服务器证书
# server-cert = /etc/ssl/certs/ssl-cert-snakeoil.pem
# server-key = /etc/ssl/private/ssl-cert-snakeoil.key
server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem
# 设置客户端最大连接数量,默认是16
max-clients = 16
# 每个用户并发设备数量
max-same-clients = 2
# 启用MTU discovery以提高性能
#try-mtu-discovery = false
try-mtu-discovery = true
# 设置默认域名为vpn.example.com
default-domain = vpn.example.com
# 修改IPv4网段配置,注意不要和本地的IP网段重合
ipv4-network = 10.10.10.0
# 将所有DNS查询都通过VPN(防止受到DNS污染)
tunnel-all-dns = true
# 设置使用Google的公共DNS
dns = 8.8.8.8
# 注释掉所有路由参数
# route = 10.10.10.0/255.255.255.0
# route = 192.168.0.0/255.255.0.0
# route = fef4:db8:1000:1001::/64
# no-route = 192.168.5.0/255.255.255.0
重启ocserv:
sudo systemctl restart ocserv
创建VPN账号:
sudo ocpasswd -c /etc/ocserv/ocpasswd username
激活IP Forwarding (重要步骤)
修改 /etc/sysctl.conf
添加:
net.ipv4.ip_forward = 1
然后执行:
sudo sysctl -p
配置防火墙的IP Masquerading (这里加设网卡接口是
ens3
)sudo iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
在防火墙上开启端口443:
sudo iptables -I INPUT -p tcp --dport 443 -j ACCEPT sudo iptables -I INPUT -p udp --dport 443 -j ACCEPT
保存防火墙配置:
sudo iptables-save > /etc/iptables.rules
创建一个systemd服务来启动时恢复iptables规则,编辑
/etc/systemd/system/iptables-restore.service
[Unit] Description=Packet Filtering Framework Before=network-pre.target Wants=network-pre.target [Service] Type=oneshot ExecStart=/sbin/iptables-restore /etc/iptables.rules ExecReload=/sbin/iptables-restore /etc/iptables.rules RemainAfterExit=yes [Install] WantedBy=multi-user.target
激活
iptables-restore
服务:sudo systemctl daemon-reload sudo systemctl enable iptables-restore
使用OpenConnect VPN Client¶
备注
详细操作步骤参考 使用OpenConnect客户端
安装 OpenConnect:
sudo apt install openconnect
连接服务器:
sudo openconnect <VPN服务器域名>
连接建立以后,就可以正常使用apt安装Google软件仓库中的软件。
OpenConnect VPN Client使用技巧¶
我在使用 openconnect
遇到以下几个问题需要解决:
需要手工输入用户名和密码
服务器证书过期后每次都要手工接受服务器证书 (早期版本可以使用
--no-cert-check
参数绕过,但是现在不行,必须明确接受服务器证书)
openconnect
提供了 -u
参数传递账号名,但是使用 -p
参数传递密码失败,所以改成 --passwd-on-stdin
从管道获取密码:
echo mypassword | sudo openconnect -u <myusernae> --passwd-on-stdin <vpnserver>:<vpn_port>
对于接受服务器证书的问题,可以使用 --servercert
参数来传递服务器证书,这样就不需要每次都手工确认一次了,所以完整的命令
echo mypassword | sudo openconnect -u <myusernae> --passwd-on-stdin --serverceet <cert> <vpnserver>:<vpn_port>
Cisco AnyConnect VPN Client¶
Cisco AnyConnnect VPN Client 和OpenConnect VPN Server (ocserv) 兼容,所以可以从Cisco官方网站下载客户端。
修改ocserv端口¶
如果在同一台主机上部署ocserv vpn server和WEB服务,例如 部署Ghost CMS ,则会遇到端口冲突问题:因为VPN也同样使用了https端口443。
解决的方法是:调整VPN Server的端口,修订成 404
端口:
修改
/etc/ocserv/ocserv.conf
tcp-port = 404 udp-port = 404
修改
/lib/systemd/system/ocserv.socket
Socket端口对应监听:[Socket] ListenStream=404 ListenDatagram=404
重新加载配置:
systemctl reload-daemon
重启服务:
systemctl restart ocserv