OpenWRT 搭建 OpenVPN 服务器

2019-11-29 11:00:42 +08:00
 hiplon

主要实现在 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 tun0cat /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:

1.OpenVPN basic

2.Openvpn 2.4 设置用户密码认证

3.原文链接

27898 次点击
所在节点    宽带症候群
11 条回复
cwbsw
2019-11-29 11:13:18 +08:00
考虑性能,换 wireguard。
考虑 QoS 和方便客户端接入,换 ipsec。
bilibilifi
2019-11-29 11:14:30 +08:00
还用 openvpn... WireGuard 不香吗?
hiplon
2019-11-29 11:18:58 +08:00
WireGuard 按我理解是不是应该做 site2site 比较方便,但是 dial up 可能不是很好管理?
buddha
2019-11-29 12:21:12 +08:00
OpenConnect/AnyConnect 也是用的 UDP
cwbsw
2019-11-29 13:27:19 +08:00
@hiplon 目前是这样没错。但你的用户多到需要考虑管理问题了吗?
zro
2019-11-29 13:36:34 +08:00
是我,会继续选择 WireGuard 吧。。比 OpenVPN 轻量多了,或者在 OpenWRT 部署 5S 也简单些吧?
hiplon
2019-11-29 14:02:53 +08:00
等我看看 wireguard 下面有没方便一点的 peers 管理,到时再试一下
hiplon
2019-11-29 14:38:16 +08:00
@cwbsw #5 如果用户更多一般是加 RADIUS 上的,主要是自己家宽也有几个朋友( 5-6 )个经常会一起连局域网打翔鹰帝国,这个时候还是不得不考虑下用户的问题,之前 openconncent 就很适合这种场景
Archeb
2019-11-29 14:56:16 +08:00
我建议 softether vpn 一次满足你的三个愿望(l2tp-ipsec sstp openvpn sevpn)
immike
2020-02-17 13:12:44 +08:00
有支持 Wireguard 的 IP 话机吗?
hanssx
2022-09-21 19:14:55 +08:00
比较难受得是 Wg 是 UDP ,如果要弄成 TCP ,Windows 下没有好用的工具,udp2raw 一直握手失败。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/624222

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX