主要实现在 OpenWRT 路由器系统下搭建 OpenVPN 服务器方便远程连接
之前一直是在 OpenWRT 使用 Openconnect VPN,因为是 SSLVPN 使用起来结合 CISCO 的 anyconnect 客户端是很方便的,但是由于现在 ISP 连这种基于 SSL 的流量也有可以做识别并封公网 IP,所以不得不考虑切换至基于 UDP 的 OpenVPN 了。
下面主要分三步:
( 1 )在 OpenWRT 安装并配置好 OpenVPN
( 2 )配置多用户方案
( 3 )结合 Luci 去显示 OpenVPN
那么现在开始吧,目前系统是使用了最新的 OpenWRT 19.07.0-rc1, 同时适用于 OpenWrt 18.06.4
1.在 OpenWRT 安装并配置好 OpenVPN
先安装好本次所需的全部软件
opkg update
opkg install openvpn-easy-rsa openvpn-mbedtls luci-app-openvpn
配置防火墙开放相应端口
# Configure firewall
uci rename firewall.@zone[0]="lan"
uci rename firewall.@zone[1]="wan"
uci rename firewall.@forwarding[0]="lan_wan"
uci del_list firewall.lan.device="tun0"
uci add_list firewall.lan.device="tun0"
uci -q delete firewall.vpn
uci set firewall.ovpn="rule"
uci set firewall.ovpn.name="Allow-OpenVPN"
uci set firewall.ovpn.src="wan"
uci set firewall.ovpn.dest_port="1194"
uci set firewall.ovpn.proto="udp"
uci set firewall.ovpn.target="ACCEPT"
uci commit firewall
/etc/init.d/firewall restart
生成服务器和客户端证书
# Configuration parameters
export EASYRSA_PKI="/etc/easy-rsa/pki"
export EASYRSA_REQ_CN="ovpnca"
# Remove and re-initialize the PKI directory
easyrsa --batch init-pki
# Generate DH parameters
# 此步会较久
easyrsa --batch gen-dh
# Create a new CA
easyrsa --batch build-ca nopass
# Generate a keypair and sign locally for a server
easyrsa --batch build-server-full server nopass
# Generate a keypair and sign locally for a client
easyrsa --batch build-client-full client nopass
生成服务器配置文件
# Generate TLS PSK
OVPN_PKI="/etc/easy-rsa/pki"
openvpn --genkey --secret ${OVPN_PKI}/tc.pem
# Configuration parameters
OVPN_DIR="/etc/openvpn"
OVPN_PKI="/etc/easy-rsa/pki"
OVPN_DEV="$(uci get firewall.lan.device | sed -e "s/^.*\s//")"
OVPN_PORT="$(uci get firewall.ovpn.dest_port)"
OVPN_PROTO="$(uci get firewall.ovpn.proto)"
OVPN_POOL="192.168.8.0 255.255.255.0"
OVPN_DNS="${OVPN_POOL%.* *}.1"
OVPN_DOMAIN="$(uci get dhcp.@dnsmasq[0].domain)"
OVPN_DH="$(cat ${OVPN_PKI}/dh.pem)"
OVPN_TC="$(sed -e "/^#/d;/^\w/N;s/\n//" ${OVPN_PKI}/tc.pem)"
OVPN_CA="$(openssl x509 -in ${OVPN_PKI}/ca.crt)"
NL=$'\n'
# Configure VPN server
umask u=rw,g=,o=
grep -l -r -e "TLS Web Server Auth" "${OVPN_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read -r OVPN_ID
do
OVPN_CERT="$(openssl x509 -in ${OVPN_PKI}/issued/${OVPN_ID}.crt)"
OVPN_KEY="$(cat ${OVPN_PKI}/private/${OVPN_ID}.key)"
cat << EOF > ${OVPN_DIR}/${OVPN_ID}.conf
verb 3
user nobody
group nogroup
dev ${OVPN_DEV}
port ${OVPN_PORT}
proto ${OVPN_PROTO}
server ${OVPN_POOL}
topology subnet
client-to-client
keepalive 10 120
persist-tun
persist-key
push "dhcp-option DNS ${OVPN_DNS}"
push "dhcp-option DOMAIN ${OVPN_DOMAIN}"
push "redirect-gateway def1"
push "persist-tun"
push "persist-key"
<dh>${NL}${OVPN_DH}${NL}</dh>
<tls-crypt>${NL}${OVPN_TC}${NL}</tls-crypt>
<ca>${NL}${OVPN_CA}${NL}</ca>
<cert>${NL}${OVPN_CERT}${NL}</cert>
<key>${NL}${OVPN_KEY}${NL}</key>
EOF
done
/etc/init.d/openvpn restart
OVPN_POOL="192.168.8.0 255.255.255.0"
定义的地址池不要和内网已有的地址冲突
push "redirect-gateway def1"
是将 OpenVPN 的网关作为默认网关,会创建默认路由指向 OpenVPN 的网关,如果只是需要访问家里的网络,可将这条按需要修改,如push "route 192.168.1.0 255.255.255.0 192.168.8.1"
用ip addr show tun0
和cat /var/run/openvpn.server.status
确认一下 OpenVPN 运行状态
生成客户端 ovpn 文件
# 先确定使用 DDNS 还是公网 IP 作为 OpenVPN 连接使用,并配置好 OVPN_SERV 参数,本次以 DDNS 地址为例子
OVPN_SERV="ddns.example.com"
# Configuration parameters
OVPN_DIR="/etc/openvpn"
OVPN_PKI="/etc/easy-rsa/pki"
OVPN_DEV="$(uci get firewall.lan.device | sed -e "s/^.*\s//")"
OVPN_PORT="$(uci get firewall.ovpn.dest_port)"
OVPN_PROTO="$(uci get firewall.ovpn.proto)"
OVPN_TC="$(sed -e "/^#/d;/^\w/N;s/\n//" ${OVPN_PKI}/tc.pem)"
OVPN_CA="$(openssl x509 -in ${OVPN_PKI}/ca.crt)"
NL=$'\n'
# Generate VPN client profiles
umask u=rw,g=,o=
grep -l -r -e "TLS Web Client Auth" "${OVPN_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read -r OVPN_ID
do
OVPN_CERT="$(openssl x509 -in ${OVPN_PKI}/issued/${OVPN_ID}.crt)"
OVPN_KEY="$(cat ${OVPN_PKI}/private/${OVPN_ID}.key)"
cat << EOF > ${OVPN_DIR}/${OVPN_ID}.ovpn
verb 3
dev ${OVPN_DEV%%[0-9]*}
nobind
client
remote ${OVPN_SERV} ${OVPN_PORT} ${OVPN_PROTO}
auth-nocache
remote-cert-tls server
<tls-crypt>${NL}${OVPN_TC}${NL}</tls-crypt>
<ca>${NL}${OVPN_CA}${NL}</ca>
<cert>${NL}${OVPN_CERT}${NL}</cert>
<key>${NL}${OVPN_KEY}${NL}</key>
EOF
done
ls ${OVPN_DIR}/*.ovpn
将该 ovpn 导入到 OpenVPN 的客户端就可以链接上 OpenVPN 服务器
至此一般的 OpenVPN Server 配置已经完成,目前存在的问题就是一个证书只能连接上一个客户端,下一步就是将会配置多用户的方案。
2.多用户模式
多用户方案有两种,一种是生成多个证书文件,每个用户单独使用一个证书;另外一种就是使用单证书配合用户密码的形式。
这两种都会贴一下配置,因为连回家主要是为了方便,所以会以用户名密码的方式为主。
多证书方式:
需要生成另外一组用户公钥和私钥
# Configuration parameters
export EASYRSA_PKI="/etc/easy-rsa/pki"
# Add one more client
easyrsa --batch build-client-full client1 nopass
然后在/etc/easy-rsa/pki/issued
找到client1.crt
,在/etc/easy-rsa/pki/private
找到client1.key
将client1.crt
的 cert 和client1.key
的 key 替换 ovpn 文件中的<cert><key>段即可生成给第二位用户的 ovpn 文件</key></cert>
单证书多用户模式:
创建用户认证脚本(checkpsw.sh)
/etc/openvpn/checkpsw.sh
#!/bin/sh
###########################################################
# checkpsw.sh (C) 2004 Mathias Sundman <mathias@openvpn.se>
#
# This script will authenticate OpenVPN users against
# a plain text file. The passfile should simply contain
# one row per user with the username first followed by
# one or more space(s) or tab(s) and then the password.
PASSFILE="/etc/openvpn/psw-file"
LOG_FILE="/etc/openvpn/openvpn-password.log"
TIME_STAMP=`date "+%Y-%m-%d %T"`
###########################################################
if [ ! -r "${PASSFILE}" ]; then
echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." >> ${LOG_FILE}
exit 1
fi
CORRECT_PASSWORD=`awk '!/^;/&&!/^#/&&$1=="'${username}'"{print $2;exit}' ${PASSFILE}`
if [ "${CORRECT_PASSWORD}" = "" ]; then
echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1
fi
if [ "${password}" = "${CORRECT_PASSWORD}" ]; then
echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}
exit 0
fi
echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1
配置执行权限
chmod +x /etc/openvpn/checkpsw.sh
配置用户密码文件
/etc/openvpn/psw-file
user1 passwd1
user2 passwd2
修改服务端配置文件
在/etc/openvpn/server.conf
后面添加
script-security 3
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
verify-client-cert none
修改客户端配置文件
删除掉<cert>
和<key>
添加如下内容:
auth-user-pass
那样就可以使用用户密码登录了。
3.OpenWRT Luci 集成
这一步主要是方便在 OpenWRT 的 Web 界面方便看到 OpenVPN 的状态信息
确保已经安装好
opkg install luci-app-openvpn
通过命令修改 luci 配置
# Provide VPN instance management
ls /etc/openvpn/*.conf \
| while read -r OVPN_CONF
do
OVPN_ID="$(basename ${OVPN_CONF%.*} | sed -e "s/\W/_/g")"
uci -q delete openvpn.${OVPN_ID}
uci set openvpn.${OVPN_ID}="openvpn"
uci set openvpn.${OVPN_ID}.enabled="1"
uci set openvpn.${OVPN_ID}.config="${OVPN_CONF}"
done
uci commit openvpn
/etc/init.d/openvpn restart
refer:
3.原文链接
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.