测试在 Vultr 提供的 CentOS 7 X64 平台,需要你已经构建好 Radius 服务器。
较早期的 AnyConnect 只能运行在思科设备上,现在 AnyConnect 可以通过兼容 AnyConnect SSL VPN 的 ocserv (OpenConnect VPN Server) 实现。在 Fedora 维护的 EPEL 仓库中已经提供了 ocserv,所以只要安装 EPEL 源即可。
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
然后安装 ocserv 软件,radcli 是对 Radius 的支持组件。
yum install -y radcli
yum install -y ocserv
AnyConnect 在连接成功后交换内容数据采用 UDP 的 DTLS,在断线重连时采用 TCP 的 TLS 来保证安全,所以需要提供 TLS 证书。自建 CA 会导致客户端在连接服务器时提示证书不信任,可以申请 SSL 证书来避免这个问题并跳过自己生成证书的步骤,对于多台 AnyConnect 服务器可以申请泛域名证书来避免每台服务器生成一张证书。我们在这里使用自建 CA,AnyConnect 所用证书可以用 GunTLS 提供的 certtool 生成,下面的命令构造了一个 RSA 算法的 2048 位私钥,请注意不要生成 AnyConnect 不支持的 ECC 证书。
certtool --generate-privkey --outfile ca.pem
这样就生成了 CA 所需的私钥 ca.pem 文件,生成 CA 的证书需要填写一些模版信息,保存到 ca.tmpl。
cn="my root ca"
organization="ca"
expiration_days=3650
serial=1
ca
signing_key
cert_signing_key
crl_signing_key
这样我们就可以生成 CA 的证书了。
certtool --generate-self-signed --load-privkey ca.pem --template ca.tmpl --outfile ca.crt
自建完成 CA 后需要生成一张供 AnyConnect 使用的终端证书。
certtool --generate-privkey --outfile anyconnect.pem
生成公钥需要填写一些模版信息,保存到 anyconnect.tmpl。
cn="你的域名 / 服务器 IP"
unit="anyconnect"
expiration_days=365
signing_key
tls_www_client
随后我们创建公钥。
certtool --generate-certificate --load-privkey anyconnect.pem --load-ca-certificate ca.crt --load-ca-privkey ca.pem --template anyconnect.tmpl --outfile anyconnect.crt
在客户端需要使用 p12 格式的证书,会提示输入密码与验证密码,如果输入了密码在使用时也会要求输入密码,可以留空。
openssl pkcs12 -export -inkey anyconnect.pem -in anyconnect.crt -certfile ca.crt -out user.p12
我们成功生成了两张证书,一张是我们自建的 CA 证书 ca.crt,一张是我们生成的 AnyConnect 使用的证书 anyconnect.crt。AnyConnect 服务器在此作为的是 Radius 的客户端,编辑 /etc/radcli/servers 中输入你的 radius 服务器地址与通信密钥,例如如下格式。
radius.example.com testing123
然后编辑 Radius Client 的配置文件 /etc/radcli/radiusclient.conf。
authserver radius.example.com
acctserver radius.example.com
编辑 /etc/ocserv/ocserv.conf 文件,找到 auth = "pam"
更改为 auth = "auth = "radius[config=/etc/radcli/radiusclient.conf,groupconfig=true]"
。
然后主要修改以下部分。
# 启用认证
acct = "radius[config=/etc/radcli/radiusclient.conf]"
# 超时时间
stats-report-time = 360
server-cert = /etc/ocserv/anyconnect.crt
server-key = /etc/ocserv/anyconnect.pem
#最大用户数量
max-clients = 16
#同一个用户最多同时登陆数
max-same-clients = 4
#tcp和udp端口
tcp-port = 443
udp-port = 443
#运行用户和组
run-as-user = ocserv
run-as-group = ocserv
#分配给VPN客户端的IP段
ipv4-network = 10.12.0.0
ipv4-netmask = 255.255.255.0
#DNS
dns = 8.8.8.8
dns = 8.8.4.4
注释掉所有的 no-route 和 route 表示所有流量均通过 AnyConnect 发送,配置防火墙。
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # 自动调整 MTU
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # NAT 转发
iptables -I INPUT -p tcp --dport 443 -j ACCEPT # 开启 443 端口的 TCP
iptables -I INPUT -p udp --dport 443 -j ACCEPT # 开启 443 端口的 UDP
随后编辑 /etc/sysctl.conf 文件存入以下内容并保存。
net.ipv4.ip_forward = 1
执行。
sysctl -p
在某些情况下可能 iptables 会无法使用,可以尝试 iptables -F 清除所有的条目后再执行以上条目,最后开启 ocserv 服务端。
systemctl start ocserv.service
或者你也可以选择弃用 firewalld 而改用 iptables。
systemctl stop firewalld
systemctl mask firewalld
yum install iptables-services -y
systemctl enable iptables