Table of Contents

FIXME This page is not fully translated, yet. Please help completing the translation.
(remove this paragraph once the translation is finished)

OpenVPN 基础

简介

目标

指导

1. 防火墙

Consider VPN network as private and assign VPN interface to LAN zone to minimize firewall setup. Allow access to VPN server from WAN zone.

# Configure firewall
uci set firewall.@zone[0].device="tun0"
uci -q delete firewall.vpn
uci set firewall.vpn="rule"
uci set firewall.vpn.name="Allow-OpenVPN"
uci set firewall.vpn.src="wan"
uci set firewall.vpn.dest_port="1194"
uci set firewall.vpn.proto="udp"
uci set firewall.vpn.target="ACCEPT"
uci commit firewall
service firewall restart

2. PKI(公钥基础设施)

使用EasyRSA来处理PKI相关的事务。如果需要,可以给私钥加上密码保护.

# Install packages
opkg update
opkg install openvpn-easy-rsa
 
# Configuration parameters
export EASYRSA_PKI="/etc/easy-rsa/pki"
export EASYRSA_REQ_CN="vpnca"
 
# Remove and re-initialize the PKI directory
easyrsa --batch init-pki
 
# Generate DH parameters
# May take a while to complete (~25m on WRT3200ACM)
easyrsa --batch gen-dh
 
# Create a new CA
easyrsa --batch build-ca nopass
 
# Generate a key pair and sign locally for vpnserver
easyrsa --batch build-server-full vpnserver nopass
 
# Generate a key pair and sign locally for vpnclient
easyrsa --batch build-client-full vpnclient nopass

3. VPN服务器的配置

安装并配置VPN服务器.

# Install packages
opkg update
opkg install openvpn-openssl
 
# Generate TLS PSK
EASYRSA_PKI="/etc/easy-rsa/pki"
openvpn --genkey --secret "${EASYRSA_PKI}/tc.pem"
 
# Configuration parameters
VPN_DEV="$(uci get firewall.@zone[0].device)"
VPN_POOL="192.168.8.0 255.255.255.0"
VPN_DNS="${VPN_POOL%.* *}.1"
VPN_DOMAIN="$(uci get dhcp.@dnsmasq[0].domain)"
EASYRSA_PKI="/etc/easy-rsa/pki"
DH_KEY="$(cat "${EASYRSA_PKI}/dh.pem")"
TC_KEY="$(sed -e "/^#/d;/^\w/N;s/\n//" "${EASYRSA_PKI}/tc.pem")"
CA_CERT="$(openssl x509 -in "${EASYRSA_PKI}/ca.crt")"
NL=$'\n'
 
# Configure VPN server
grep -l -r -e "TLS Web Server Authentication" "${EASYRSA_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read VPN_ID
do
VPN_CONF="/etc/openvpn/${VPN_ID}.conf"
VPN_CERT="$(openssl x509 -in "${EASYRSA_PKI}/issued/${VPN_ID}.crt")"
VPN_KEY="$(cat "${EASYRSA_PKI}/private/${VPN_ID}.key")"
cat << EOF > "${VPN_CONF}"
verb 3
user nobody
group nogroup
dev ${VPN_DEV}
port 1194
proto udp
server ${VPN_POOL}
topology subnet
client-to-client
keepalive 10 120
persist-tun
persist-key
push "dhcp-option DNS ${VPN_DNS}"
push "dhcp-option DOMAIN ${VPN_DOMAIN}"
push "redirect-gateway def1"
push "persist-tun"
push "persist-key"
<dh>${NL}${DH_KEY}${NL}</dh>
<tls-crypt>${NL}${TC_KEY}${NL}</tls-crypt>
<ca>${NL}${CA_CERT}${NL}</ca>
<cert>${NL}${VPN_CERT}${NL}</cert>
<key>${NL}${VPN_KEY}${NL}</key>
EOF
chmod "u=rw,g=,o=" "${VPN_CONF}"
done
service openvpn restart

See also: Instance management, Dual-stack gateway

4. 客户端的配置文件(profiles)

为VPN客户端生成配置文件(profiles)。 如果需要,也可以设置 DDNS client

# Fetch WAN IP address
source /lib/functions/network.sh
network_find_wan NET_IF
network_get_ipaddr VPN_SERV "${NET_IF}"
 
# Fetch FQDN from DDNS client
VPN_FQDN="$(uci -q get "$(uci -q show ddns \
| sed -n -e "/\.enabled='1'$/s//.lookup_host/p" \
| sed -n -e "1p")")"
if [ -n "${VPN_FQDN}" ]
then
VPN_SERV="${VPN_FQDN}"
fi
 
# Configuration parameters
VPN_CONF="/etc/openvpn/vpnserver.conf"
VPN_PORT="$(sed -n -e "/^port\s/s///p" "${VPN_CONF}")"
VPN_PROTO="$(sed -n -e "/^proto\s/s///p" "${VPN_CONF}")"
VPN_DEV="$(sed -n -e "/^dev\s/s///p" "${VPN_CONF}")"
EASYRSA_PKI="/etc/easy-rsa/pki"
TC_KEY="$(sed -e "/^#/d;/^\w/N;s/\n//" "${EASYRSA_PKI}/tc.pem")"
CA_CERT="$(openssl x509 -in "${EASYRSA_PKI}/ca.crt")"
NL=$'\n'
 
# Generate VPN client profiles
grep -l -r -e "TLS Web Client Authentication" "${EASYRSA_PKI}/issued" \
| sed -e "s/^.*\///;s/\.\w*$//" \
| while read VPN_ID
do
VPN_CONF="/etc/openvpn/${VPN_ID}.ovpn"
VPN_CERT="$(openssl x509 -in "${EASYRSA_PKI}/issued/${VPN_ID}.crt")"
VPN_KEY="$(cat "${EASYRSA_PKI}/private/${VPN_ID}.key")"
cat << EOF > "${VPN_CONF}"
verb 3
dev ${VPN_DEV%%[0-9]*}
nobind
client
remote ${VPN_SERV} ${VPN_PORT} ${VPN_PROTO}
auth-nocache
remote-cert-tls server
<tls-crypt>${NL}${TC_KEY}${NL}</tls-crypt>
<ca>${NL}${CA_CERT}${NL}</ca>
<cert>${NL}${VPN_CERT}${NL}</cert>
<key>${NL}${VPN_KEY}${NL}</key>
EOF
chmod "u=rw,g=,o=" "${VPN_CONF}"
done
ls /etc/openvpn/*.ovpn

Perform OpenWrt backup. Extract client profiles from the archive and import them to your clients.

See also: Client fixes, Recommended clients

测试

建立VPN连接。检查客户端的流量全部经过VPN服务器的网关。

traceroute openwrt.org
traceroute6 openwrt.org

检查客户端的公网IP地址: * ipleak.net

确保在客户端一侧没有DNS leak。 * dnsleaktest.com

Delegate a public IPv6 prefix to the IPv6 VPN network to use IPv6 by default. * ipv6-test.com

Troubleshooting

Collect and analyze the following information.

# Restart services
service log restart; service openvpn restart; sleep 10
 
# Log and status
logread -e openvpn; netstat -l -n -p | grep -e openvpn
 
# Runtime configuration
pgrep -f -a openvpn
ip address show; ip route show table all
ip rule show; ip -6 rule show; nft list ruleset
 
# Persistent configuration
uci show network; uci show firewall; uci show openvpn
head -n -0 /etc/openvpn/*.conf