V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hiplon
V2EX  ›  宽带症候群

OpenWRT 搭建 OpenVPN 服务器

  •  1
     
  •   hiplon · 2019-11-29 11:00:42 +08:00 · 28331 次点击
    这是一个创建于 1820 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    OpenWRT Firewall

    生成服务器和客户端证书

    # 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 运行状态

    OpenVPN Status

    生成客户端 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 服务器

    Connection Status

    至此一般的 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 <[email protected]>
    #
    # 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
    

    Luci Status

    refer:

    1.OpenVPN basic

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

    3.原文链接

    11 条回复    2022-09-21 19:14:55 +08:00
    cwbsw
        1
    cwbsw  
       2019-11-29 11:13:18 +08:00   ❤️ 1
    考虑性能,换 wireguard。
    考虑 QoS 和方便客户端接入,换 ipsec。
    bilibilifi
        2
    bilibilifi  
       2019-11-29 11:14:30 +08:00 via iPhone
    还用 openvpn... WireGuard 不香吗?
    hiplon
        3
    hiplon  
    OP
       2019-11-29 11:18:58 +08:00
    WireGuard 按我理解是不是应该做 site2site 比较方便,但是 dial up 可能不是很好管理?
    buddha
        4
    buddha  
       2019-11-29 12:21:12 +08:00
    OpenConnect/AnyConnect 也是用的 UDP
    cwbsw
        5
    cwbsw  
       2019-11-29 13:27:19 +08:00   ❤️ 1
    @hiplon 目前是这样没错。但你的用户多到需要考虑管理问题了吗?
    zro
        6
    zro  
       2019-11-29 13:36:34 +08:00
    是我,会继续选择 WireGuard 吧。。比 OpenVPN 轻量多了,或者在 OpenWRT 部署 5S 也简单些吧?
    hiplon
        7
    hiplon  
    OP
       2019-11-29 14:02:53 +08:00
    等我看看 wireguard 下面有没方便一点的 peers 管理,到时再试一下
    hiplon
        8
    hiplon  
    OP
       2019-11-29 14:38:16 +08:00
    @cwbsw #5 如果用户更多一般是加 RADIUS 上的,主要是自己家宽也有几个朋友( 5-6 )个经常会一起连局域网打翔鹰帝国,这个时候还是不得不考虑下用户的问题,之前 openconncent 就很适合这种场景
    Archeb
        9
    Archeb  
       2019-11-29 14:56:16 +08:00 via Android
    我建议 softether vpn 一次满足你的三个愿望(l2tp-ipsec sstp openvpn sevpn)
    immike
        10
    immike  
       2020-02-17 13:12:44 +08:00
    有支持 Wireguard 的 IP 话机吗?
    hanssx
        11
    hanssx  
       2022-09-21 19:14:55 +08:00
    比较难受得是 Wg 是 UDP ,如果要弄成 TCP ,Windows 下没有好用的工具,udp2raw 一直握手失败。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2706 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 14:48 · PVG 22:48 · LAX 06:48 · JFK 09:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.