OpenConnect 是一个用于连接到虚拟专用网络 (VPN) 的开源软件应用程序,它实现了安全的点对点连接。它最初是作为 Cisco 专有 AnyConnect SSL VPN 客户端的开源替代品编写的。而 ocserv 是 OpenConnect 的服务端。由于很多厂商需要用 Cisco 的 AnyConnect VPN 在海外开展业务,所以虽然 OpenConnect 的流量特征明显,但是受影响却很小。
准备系统
net.ipv4.neigh.default.base_reachable_time_ms = 600000
net.ipv4.neigh.default.mcast_solicit = 20
net.ipv4.neigh.default.retrans_time_ms = 250
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.eth0.rp_filter=0
net.ipv4.conf.eth1.rp_filter=0
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
net.ipv4.tcp_fastopen=3
net.ipv4.ip_forward=1
# disable ping echo
# net.ipv4.icmp_echo_ignore_all=1
安装 certbot,配置证书
openconnect 需要用 ssl 证书来加密连接,所以需要用 Let’s Encrypt 来获取一个证书。
$ sudo apt update
$ sudo apt install certbot
先将域名做 dns 设置,指向 vps,然后签发一个 tls 证书:
$ certbot certonly --standalone --preferred-challenges http --agree-tos --email you@gmail.com -d vpn.example.com
安装 ocserv:
$ sudo apt install ocserv
配置 ocserv.conf:
server-cert = /etc/letsencrypt/live/vpn.example.com/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.example.com/privkey.pem
客户端证书认证
ocserv 支持多种客户端登陆认证方式,这里我们用证书登陆。 设置客户端证书:
$ apt install gnutls-bin
$ mkdir /etc/ocserv/ssl/
$ cd /etc/ocserv/ssl
创建 CA 的私钥:
$ certtool --generate-privkey --outfile ca-privkey.pem
新建 CA 证书的模板
$ vim ca-cert.cfg
# X.509 Certificate options
# The organization of the subject.
organization = "vpn.example.com"
# The common name of the certificate owner.
cn = "Example CA"
# The serial number of the certificate.
serial = 001
# In how many days, counting from today, this certificate will expire. Use -1 if there is no expiration date.
expiration_days = -1
# Whether this is a CA certificate or not
ca
# Whether this certificate will be used to sign data
signing_key
# Whether this key will be used to sign other certificates.
cert_signing_key
# Whether this key will be used to sign CRLs.
crl_signing_key
生成 CA 证书:
$ certtool --generate-self-signed --load-privkey ca-privkey.pem --template ca-cert.cfg --outfile ca-cert.pem
创建客户端密钥
$ certtool --generate-privkey --outfile client-privkey.pem
客户端证书模板
$ vim client-cert.cfg
# X.509 Certificate options
# The organization of the subject.
organization = "vpn.example.com"
# The common name of the certificate owner.
cn = "John Doe"
# A user id of the certificate owner.
uid = "username"
# In how many days, counting from today, this certificate will expire. Use -1 if there is no expiration date.
expiration_days = 3650
# Whether this certificate will be used for a TLS server
tls_www_client
# Whether this certificate will be used to sign data
signing_key
# Whether this certificate will be used to encrypt data (needed
# in TLS RSA ciphersuites). Note that it is preferred to use different
# keys for encryption and signing.
encryption_key
用 CA 密钥签发一个客户端证书
$ certtool --generate-certificate --load-privkey client-privkey.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-privkey.pem --template client-cert.cfg --outfile client-cert.pem
组合客户端私钥和证书为一个 PKCS #12 文件
$ certtool --to-p12 --load-privkey client-privkey.pem --load-certificate client-cert.pem --pkcs-cipher aes-256 --outfile client.p12 --outder
ios 客户端不支持 aes-256 算法,需要用 3des-pkcs12 算法
$ certtool --to-p12 --load-privkey client-privkey.pem --load-certificate client-cert.pem --pkcs-cipher 3des-pkcs12 --outfile ios-client.p12 --outder
开启证书登陆
$ vim /etc/ocserv/ocserv.conf
auth = "certificate"
ca-cert = /etc/ocserv/ssl/ca-cert.pem
$ systemctl restart ocserv
剩余的配置
keepalive = 30
try-mtu-discovery = true
default-domain = vpn.example.com
ipv4-network = 10.10.10.0
tunnel-all-dns = true
# 注释下面的所有
#route = 10.0.0.0/8
#route = 172.16.0.0/12
#route = 192.168.0.0/16
#route = fd00::/8
#route = default
#no-route = 192.168.5.0/255.255.255.0
开启 ip 转发
net.ipv4.ip_forward = 1
iptables,源地址转换:
$ iptables -t nat -I POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
自动更新 Let’s Encrypt 证书
crontab -e
@daily certbot renew --quiet && systemctl restart ocserv
关闭 tls1.0 和 tls1.1
这两个版本的 tls 已经很老了,现在最新的都会用1.2或者1.3版本
tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128"
改为
tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128:-VERS-TLS1.0:-VERS-TLS1.1"
检测
openssl s_client -connect vpn.your-domain.com:443 -tls1
openssl s_client -connect vpn.your-domain.com:443 -tls1.1
客户端配置
linux 可以用 NetworkManager 管理 openconnect 客户端连接,需要安装networkmanager-openconnect
这个包。ios 设备将 p12 文件发送到设备上,然后用 AnyConnect 打开,导入证书。
报错
Read error on DTLS session: The transmitted packet is too large (EMSGSIZE).
需要设置一个小的 mtu 值:
ocserv.conf -> mtu = 1466