本帖最后由 有事您说话 于 2016-11-18 13:46 编辑
PS. 文章出自 http://blog.ltns.info/linux/openwrt_ocserv_vpn_client_smart_proxy/
于是决定在路由器上安装 ocserv(兼容 Cisco AnyConnect)作为 VPN Server,未越狱的 iOS设备等在外面通过移动互联网作为 VPN Client登录进来后,就可以像路由器内网侧用户端那样实现智能分流翻WALL,而且因为无需服务端推送路由所以登录的速度也比较快。
VPN服务端的设置 opkg update opkg install ocserv #opkg install luci-app-ocserv #Gargoyle固件不能安装luci程序 /etc/init.d/ocserv enable #设置随路由器开机自启动 /etc/init.d/ocserv start #启动ocserv
注:只有配置了LuCI这个web前端的OpenWrt才可以安装luci程序,且只适用于ocserv的用户名/密码方式,不支持证书方式。如果只需要 ocserv的用户名/密码方式登录,可以参考下图在luci界面里进行设置,然后直接到步骤四
[/url] 不过还是建议采用证书方式,客户端访问 VPN服务器更安全、也更便捷。
步骤二:
如上启动 ocserv之后,在路由器上会自动生成如下七个文件 /etc/ocserv/pki/ca.tmpl #模板文件
/etc/ocserv/pki/server.tmpl
/etc/ocserv/ca.pem #ca证书
/etc/ocserv/ca-key.pem
/etc/ocserv/ocserv.conf.template #示例配置文件
/etc/ocserv/server-cert.pem #服务器证书
/etc/ocserv/server-key.pem 尚缺少用户证书,先新建一个用户模板文件 /etc/ocserv/pki/client.tmpl cn = client unit = "users" expiration_days = 3650 #证书有效期十年,可自定义 signing_key tls_www_client
然后执行如下命令生成用户证书 cd /etc/ocserv ln -s pki/ca.tmpl ca.tmpl #制作软链接文件 ln -s pki/server.tmpl server.tmpl ln -s ca.pem ca-cert.pem cp pki/client.tmpl client.tmpl cp ocserv.conf.template ocserv.conf
certtool --generate-privkey --outfileuser-key.pem
certtool --generate-certificate--load-privkey user-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkeyca-key.pem --template client.tmpl --outfile user-cert.pem 客户端证书 user-cert.pem 还不能直接使用(除了 [url=http://www.infradead.org/openconnect/gui.html]ocserv官网 推荐的Windows客户端 openconnect-gui 之外),需通过 OpenSSL转换成 .p12格式 openssl pkcs12 -export -inkey user-key.pem-in user-cert.pem -name "client" -certfile ca-cert.pem -caname"VPN CA" -out user-cert.p12 #按提示设置证书使用密码,或直接回车不设密码
步骤三:
修改配置文件 /etc/ocserv/ocserv.conf listen-host-is-dyndns = true #针对路由器使用动态域名的情形 auth = "certificate" max-clients = 16 max-same-clients = 10 tcp-port = 443 #默认的监听端口号 udp-port = 443 keepalive = 32400 dpd = 240 mobile-dpd = 1800 try-mtu-discovery = true server-cert = /etc/ocserv/server-cert.pem server-key = /etc/ocserv/server-key.pem ca-cert = /etc/ocserv/ca-cert.pem tls-priorities ="NORMAL:%SERVER_PRECEDENCE:%COMPAT" auth-timeout = 40 mobile-idle-timeout cookie-timeout = 86400000 rekey-time = 86400000 rekey-method = ssl use-utmp = true use-occtl = true pid-file = /var/run/ocserv.pid socket-file = /var/run/ocserv-socket run-as-user = ocserv #用户:用户组需和实际的一致 run-as-group = ocserv net-priority = 5 cgroup = "cpuset,cpu:test" device = vpns ipv4-network = 10.10.0.0 ipv4-netmask = 255.255.255.0 dns = 10.10.0.1 #可使用路由器的LAN IP,但建议还是用ocserv网络的 ping-leases = false output-buffer = 10 #route = ip网段/子网掩码 #注释掉所有路由推送即可实现全局路由,即,客户端所有流量走VPN route-add-cmd = "ip route add %{R} dev%{D}" route-del-cmd = "ip route delete %{R} dev%{D}" cisco-client-compat =true custom-header = "X-DTLS-MTU: 1200" custom-header = "X-CSTP-MTU: 1200" 注:跟VPS上用的配置文件不一致的地方已用红色字体标出,其他参数详见示例配置文件里的详细说明,或者见参考文章,这里不再赘述。 以及ocserv的启动脚本 /etc/init.d/ocserv ... start() { rm -f /var/etc/ocserv.conf ln -s /etc/ocserv/ocserv.conf/var/etc/ocserv.conf service_start/usr/sbin/ocserv -c /var/etc/ocserv.conf }
stop() { service_stop/usr/sbin/ocserv # delay needed to avoid restart failure sleep 3 } reload() { rm -f /var/etc/ocserv.conf ln -s /etc/ocserv/ocserv.conf/var/etc/ocserv.conf /usr/bin/occtlshow status >/dev/null 2>&1 iftest $? != 0;then start else /usr/bin/occtlreload fi }
步骤四:
修改自定义防火墙文件 /etc/firewall.user,添加如下五行内容 iptables -I INPUT -p tcp --dport 443 -j ACCEPT iptables -I INPUT -p udp --dport 443 -j ACCEPT
iptables -t nat -I POSTROUTING -s 10.10.0.0/24 -o pppoe-wan -j MASQUERADE iptables -I FORWARD -i vpns+ -s 10.10.0.0/24 -j ACCEPT iptables -I INPUT -i vpns+ -s 10.10.0.0/24 -j ACCEPT
重启ocserv和防火墙 ip addr add 10.10.0.1/24 dev eth0.2 #手工添加ocserv网络的LAN IP,如绑定的WAN网卡不是 eth0.2请根据自己的实际情况修改 /etc/init.d/ocserv restart /etc/init.d/firewall restart
注:OpenWrt BB 14.07官方源的ocserv 0.8.9其LAN IP地址不固定,只能手工添加否则DNS失效。当然,也可直接使用路由器的LAN IP如 “dns = 192.168.1.1”,不过考虑到有时VPN客户端会从某个同样为 192.168.1.0/24 的局域网发起连接,会造成网络冲突,因此还是建议把dns设置为ocserv网络的。另外,ocserv作者提到 0.9.2版本(有兴趣的可尝试OpenWrt trunk)不再需要手工添加,ocserv会自动生成。
步骤五:
OpenWrt固件的web管理可能已启用 https协议,导致ocserv启动失败并提示443端口已被占用,这时要么修改ocserv的监听端口,要么关闭web管理的 https协议,即,修改 /etc/config/uhttpd文件,注释掉其中的两行内容(Gargoyle固件可在GUI界面关闭) # listlisten_https '0.0.0.0:443' # listlisten_https '[::]:443' 注:完成后需执行 /etc/init.d/uhttpd restart 以使修改生效。
至此,ocserv服务端的设置就已完成。另外,还可以参考 之前的文章 中提及的脚本,以方便用户证书的制作。 最后,建议把路由器上的模板文件和(除了服务端证书之外的)所有证书文件备份到本地电脑硬盘,这样将来比如路由器重刷固件或者迁移到另一个路由器时,无需重新制作各个客户端证书并一一通知对方更新了。当然,到时路由器上的服务器证书还是需要重新制作一下。 #在前述的步骤一之后上传备份的模板和ca证书覆盖,然后在步骤二之后执行如下命令重新制作服务器证书 cd /etc/ocserv certtool --generate-certificate--load-privkey server-key.pem --load-ca-certificate ca-cert.pem--load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
/etc/init.d/ocserv restart
VPN客户端的设置 回到主界面即可开始连接,若DNS无效可启用 FIPS Mode后再试
[url=http://blog.ltns.info/wp-content/uploads/2015/03/iOS_AnyConnect_settings.jpg]
另外,还是同一个客户端软件,再添加一个VPN连接(服务器地址栏填入VPS的,并选择相应的证书),就可以直接登录VPS上的ocserv服务端了,只是服务端推送路由的数量有限制,但可以作为备用。
补充1:
VPN连接时,因为是免费的私有证书所以会提示 “不可信来源”,另外,还会提示 “证书与服务器名称不符”,可无视警告点继续。
[/url] 不过有强迫症的话 ,可以修改路由器上的服务器模板文件 /etc/ocserv/pki/server.tmpl的第一行 cn=Gargoyle #改成cn=路由器动态域名 serial=2 expiration_days=-1 #有效期至9999年,但有的平台如iOS7登录时可能识别为1970年(会提示证书过期了,但不影响使用),可自行修改 signing_key encryption_key 注:如需要,ca模板文件 /etc/ocserv/pki/ca.tmpl 里的有效期也可以修改一下。 然后重新制作ca证书(不是必须的)和服务器证书,并重启ocserv服务端。 #certtool --template/etc/ocserv/pki/ca.tmpl --generate-self-signed --load-privkey/etc/ocserv/ca-key.pem --outfile/etc/ocserv/ca.pem #ca证书可以不重新制作,若重新制作了,则用户证书相应地也要重新制作一遍
certtool --template/etc/ocserv/pki/server.tmpl --generate-certificate --load-privkey/etc/ocserv/server-key.pem --load-ca-certificate /etc/ocserv/ca.pem--load-ca-privkey /etc/ocserv/ca-key.pem --outfile /etc/ocserv/server-cert.pem
/etc/init.d/ocserv restart 只要VPN服务端配置文件ocserv.conf文件里的 default-domain、服务器证书里的 cn 以及VPN客户端设置里的服务器地址,这三者一致,VPN连接时就不会提示 “证书与服务器名称不符”。 至于要消除 “不可信来源” 的提示,可以去申请比如首年免费的 [url=https://www.startssl.com/]starssl证书,这里 有人折腾过。
补充2:
前面设置过的ocserv随路由器开机自启动的功能有时可能会失效,可以在 /etc/rc.local文件中添加两行 /etc/init.d/ocserv restart sleep 5
还可以创建一个检查用脚本(以防ocserv进程意外被杀),如 /root/ocservup.sh,内容如下 #!/bin/sh killall -0 ocserv 2> /dev/null if [ $? != 0 ] then logger \"$0: Starting ocserv ...\" /usr/sbin/ocserv -c /var/etc/ocserv.conf else logger \"$0: ocserv already running(pidof ocserv)\" fi 注:创建后需执行 chmod +x /root/ocservup.sh,以添加可执行属性。 然后把该脚本添加到定时任务 /etc/crontabs/root 3 */2 * * * /root/ocservup.sh #每两小时检查一次 不过 CC固件里的 dnsmasq-full这个软件默认启用了localservice,按照 OpenWRT wiki页面 里的说法,意为只接受来自本地 subnet的dns查询请求,这就会导致 vpn客户端的dns失效。 但在 luci界面中没找到修改该参数的地方,于是只好编辑启动脚本 /etc/init.d/dnsmasq,注释掉或删掉对应的如下一行 ... append_bool"$cfg" proxydnssec "--proxy-dnssec" # append_bool "$cfg" localservice"--local-service" append_bool"$cfg" quietdhcp "--quiet-dhcp" ...
最后重启一下 dnsmasq服务 /etc/init.d/dnsmasq restart
2016.10.24 更新
新版本的 ocserv配置文件有点不同,贴上我自己用的,供参考 listen-host-is-dyndns = true auth = "certificate" max-clients = 16 max-same-clients = 10 tcp-port = 443 udp-port = 443 keepalive = 32400 dpd = 240 mobile-dpd = 1800 try-mtu-discovery = true server-cert = /etc/ocserv/server-cert.pem server-key = /etc/ocserv/server-key.pem ca-cert = /etc/ocserv/ca-cert.pem cert-user-oid = 2.5.4.3 #cert-group-oid = 2.5.4.11 tls-priorities ="NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0" auth-timeout = 40 mobile-idle-timeout cookie-timeout = 86400000 rekey-time = 86400000 rekey-method = ssl connect-script = /etc/ocserv/connect-script disconnect-script = /etc/ocserv/connect-script use-utmp = true use-occtl = true pid-file = /var/run/ocserv.pid socket-file = /var/run/ocserv-socket run-as-user = ocserv run-as-group = ocserv net-priority = 5 cgroup = "cpuset,cpu:test" device = vpns ipv4-network = 10.10.0.0 ipv4-netmask = 255.255.255.0 dns = 10.10.0.1 ping-leases = false output-buffer = 10 #route = ip网段/子网掩码 route-add-cmd = "ip route add %{R} dev%{D}" route-del-cmd = "ip route delete %{R} dev%{D}" cisco-client-compat =true custom-header = "X-DTLS-MTU: 1200" custom-header = "X-CSTP-MTU: 1200"
其中的脚本文件 /etc/ocserv/connect-script 可用于比如识别正在连接的用户信息(如下所示)等,或者只保留首尾两行即可。 #!/bin/sh #echo $USERNAME : $REASON : $DEVICE case "$REASON" in connect) echo $USERNAME "connected" >>/tmp/ocservinfo date >> /tmp/testocserv echo $REASON $USERNAME $DEVICE $IP_LOCAL$IP_REMOTE $IP_REAL >> /tmp/ocservinfo ;; disconnect) echo $USERNAME "disconnected">> /tmp/ocservinfo date >> /tmp/ocservinfo ;; esac exit 0
最后还要添加该文件的可执行属性,重启ocserv chmod +x /etc/ocserv/connect-script /etc/init.d/ocserv restart
|