需求场景:需要在本地直接访问阿里云服务器所有机器的内网 ip 和静态 DNS 解析域名。
对比了阿里的 vpn 付费网关和 Cloudflare Zero Trust、 WireGuard、ZeroTier、OpenVPN、SSLVPN 等服务和协议,各有优缺点,这里记录一下通过 OpenVPN 使本地客户端访问服务器内网。

网上可参考的文章:
使用openvpn连通多个机房内网 | 小小郭的博客
企业级OpenVPN搭建 | Maxbit

OpenVPN 服务器一键安装脚本:openvpn-install · GitHub
WireGuard VPN 服务器一键安装脚本: wireguard-install · GitHub
IPsec VPN 服务器一键安装脚本: setup-ipsec-vpn · GitHub

OpenVPN 客户端下载:OpenVPN Connect - VPN For Your Operating System | OpenVPN

由于手搓安装好了 OpenVPN 之后才看到一键安装脚本,下面内容作为手动安装参考记录。

OpenVPN 组内网

环境准备

  • 服务器环境:阿里云,内网网段 172.17.211.0/24
  • 服务器角色:VPN 服务器(172.17.211.81),其他内网设备(172.17.211.82,172.17.211.83)
  • 需求:通过 OpenVPN 连接后,能够访问所有内网设备并使用静态域名(ddp1, ddp2, ddp3)

服务器和客户端最好都配置 hosts 文件。

  • linux 在 /etc/hosts
  • windows 在 C:\Windows\System32\drivers\etc\hosts
    1
    2
    3
    172.17.211.81   ddp1
    172.17.211.82 ddp2
    172.17.211.83 ddp3

OpenVPN 服务器配置

  • 安装 OpenVPN 和 Easy-RSA

    1
    2
    sudo apt-get update
    sudo apt-get install openvpn easy-rsa
  • 设置 Easy-RSA

    1
    2
    make-cadir ~/openvpn-ca
    cd ~/openvpn-ca
  • 配置 Easy-RSA 变量
    编辑 vars 文件,设置所需的变量:vim ~/openvpn-ca/vars

    1
    2
    3
    4
    5
    6
    set_var EASYRSA_REQ_COUNTRY "CN"
    set_var EASYRSA_REQ_PROVINCE "hn"
    set_var EASYRSA_REQ_CITY "zz"
    set_var EASYRSA_REQ_ORG "Awehome"
    set_var EASYRSA_REQ_EMAIL "[email protected]"
    set_var EASYRSA_REQ_OU "IT Department"

    source vars

  • 构建 CA 和生成服务器证书及密钥

    1
    2
    3
    4
    5
    6
    7
    8
    # 初始化 PKI
    ./easyrsa init-pki
    # 生成 CA,你会被提示输入 CA 的名称,按默认值即可
    ./easyrsa build-ca nopass
    # 生成服务器证书和密钥,按提示输入服务器的Common Name,通常使用 `server`作为请求文件名。
    ./easyrsa gen-req server nopass
    # 签署服务器证书,提示确认请求并输入 CA 密码,按提示操作。
    ./easyrsa sign-req server server
  • 生成 Diffie-Hellman 参数、HMAC 签名密钥和客户端证书

    1
    2
    3
    4
    5
    6
    7
    ./easyrsa gen-dh
    # 生成 HMAC 签名密钥
    openvpn --genkey secret ta.key

    ./easyrsa gen-req client1 nopass
    ./easyrsa sign-req client client1

  • 配置 OpenVPN 服务
    vim /etc/openvpn/server.conf
    我这里配置了分配给客户端的 ip 段,和阿里云局域网一个网段,目的是访问其他局域网机器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    port 1194                         # OpenVPN 服务器端口
    proto udp # 使用 UDP 协议
    dev tun # 使用 TUN 设备(隧道模式)
    ca ca.crt # CA 证书路径
    cert server.crt # 服务器证书路径
    key server.key # 服务器密钥路径
    dh dh.pem # Diffie-Hellman 参数路径
    # server 10.8.0.0 255.255.255.0 # OpenVPN 默认的分配给客户端的IP范围
    server 172.17.211.240 255.255.255.240 # 使用一个小的与内网相同的网段上的地址池,例如172.17.211.240到172.17.211.254
    ifconfig-pool-persist ipp.txt # 保持客户端IP地址池
    # push "redirect-gateway def1 bypass-dhcp" # 将客户端的默认网关重定向到VPN
    push "dhcp-option DNS 8.8.8.8" # 推送DNS配置给客户端
    push "dhcp-option DNS 8.8.4.4" # 推送DNS配置给客户端
    push "route 172.17.211.0 255.255.255.0" # 推送内网路由到客户端,确保加入vpn后能访问内网资源
    keepalive 10 120 # 保持VPN连接
    auth SHA256 # 使用 SHA256 进行认证
    tls-auth ta.key 0 # 使用 HMAC 签名密钥
    cipher AES-256-CBC # 使用 AES-256-CBC 加密
    user nobody # 使用非特权用户
    group nogroup # 使用非特权用户组
    persist-key # 保持密钥持久化
    persist-tun # 保持隧道持久化
    status /var/log/openvpn/status.log # 状态日志文件路径
    log-append /var/log/openvpn/openvpn.log # 日志文件路径
    verb 3 # 日志详细级别
    tls-server # 这行确保OpenVPN在服务器模式下运行
  • push "redirect-gateway def1 bypass-dhcp"
    如果需要只有访问特定内网段的流量才通过 VPN,其它流量仍通过本地网络访问互联网,需要注释掉这行。如果你希望将所有流量都通过 VPN,需要保留这行配置。我这里注释掉了。

分配给客户端的子网 172.17.211.240172.17.211.254

  • 网络地址:172.17.211.240(不可用)

  • 可用地址:172.17.211.241172.17.211.254(14 个地址)

  • 广播地址:172.17.211.255(不可用)
    需要通过 ifconfig 查看,确保服务器上面,子网没有与现有网络冲突。

  • 复制证书和密钥到 OpenVPN 目录:
    这些生成的证书在 ~/openvpn-ca/ 下,证书文件夹 pki

    1
    sudo cp pki/ca.crt pki/private/server.key pki/issued/server.crt pki/dh.pem ta.key /etc/openvpn/

配置防火墙和路由

  • 启用 IP 转发
    编辑 /etc/sysctl.conf 文件
    1
    sudo sysctl -w net.ipv4.ip_forward=1

应用配置

1
sudo sysctl -p

确保包含 net.ipv4.ip_forward = 1

  • 防火墙配置
    允许防火墙通过 OpenVPN 端口

    1
    2
    3
    sudo ufw allow 1194/udp
    sudo ufw allow OpenSSH
    sudo ufw enable # 内网防火墙我觉得不要开了

    记得阿里云安全组开启 1194/udp 端口

  • 配置 iptables

按需配置
方案一:VPN 客户端通过服务器访问互联网,即所有流量都通过 VPN(用这个就行,后续在客户端配置中忽略从服务器推送的路由)
最新测试,必须添加这个,不然访问不了集群其他机器。

1
2
3
4
5
6
sudo iptables -t nat -A POSTROUTING -s 172.17.211.240/28 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -s 172.17.211.240/28 -j ACCEPT

# 允许所有已经建立的连接或相关的连接通过防火墙,确保返回流量能够通过防火墙
sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

方案二:在访问特定网段(如内网172.17.211.0/24)时走 VPN,而其他流量仍走本地网络

1
2
3
4
sudo iptables -A FORWARD -s 172.17.211.240/28 -d 172.17.211.0/24 -j ACCEPT
sudo iptables -A FORWARD -s 172.17.211.0/24 -d 172.17.211.240/28 -j ACCEPT
# 允许所有已经建立的连接或相关的连接通过防火墙,确保返回流量能够通过防火墙
sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

允许从 VPN 客户端(172.17.211.240/28)发往内网服务器(172.17.211.0/24)的流量通过防火墙。
允许内网服务器(172.17.211.0/24)发往 VPN 客户端(172.17.211.240/28)的流量通过防火墙。

  • -A FORWARD:将规则添加到 FORWARD 链中,FORWARD 链处理转发的流量。
  • -s 172.17.211.240/28:指定源地址范围,即从 VPN 客户端分配的 IP 地址池发出的流量(172.17.211.240 到 172.17.211.254)。-d 172.17.211.0/24:指定目标地址范围,即内网服务器所在的 IP 地址范围(172.17.211.0 到 172.17.211.255)。-j ACCEPT:允许这些符合条件的流量通过。

删除 iptables 规则:
-A 是添加,-D 是删除。
例如删除方案一的规则

1
2
3
sudo iptables -t nat -D POSTROUTING -s 172.17.211.240/28 -o eth0 -j MASQUERADE
sudo iptables -D FORWARD -s 172.17.211.240/28 -j ACCEPT
sudo iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

添加方案二

1
2
3
sudo iptables -A FORWARD -s 172.17.211.240/28 -d 172.17.211.0/24 -j ACCEPT
sudo iptables -A FORWARD -s 172.17.211.0/24 -d 172.17.211.240/28 -j ACCEPT
sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  • 检查和保存 iptables 规则
    检查 iptables
    1
    2
    sudo iptables -L -v -n
    sudo iptables -t nat -L -v -n
1
2
3
4
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * * 172.17.211.240/28 172.17.211.0/24
0 0 ACCEPT all -- * * 172.17.211.0/24 172.17.211.240/28

若一切正常,保存规则以在重启后保持

1
2
3
sudo apt-get install iptables-persistent
# 保存防火墙规则
sudo netfilter-persistent save
  • 启动 OpenVPN 服务
    1
    2
    3
    4
    5
    6
    sudo systemctl start openvpn@server
    sudo systemctl enable openvpn@server
    # 查看状态
    sudo systemctl status openvpn@server
    # 重启
    sudo systemctl restart openvpn@server

客户端配置

  • 创建客户端配置目录和基础配置文件
    1
    2
    mkdir -p ~/client-configs/keys
    chmod -R 700 ~/client-configs

创建 base.conf 文件:
请将 YOUR_SERVER_IP 替换为服务器公网 IP 地址
推送内网路由,只有访问内网 172.17.211.0/24 的流量会通过 VPN。route-nopull 是关键配置,不添加后续客户端会无法访问互联网。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
client
dev tun
proto udp
remote YOUR_SERVER_IP 1194 # 替换为你的服务器公网 IP 和端口
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA256
cipher AES-256-CBC
key-direction 1 # 这行表示客户端使用 HMAC 密钥
verb 3

# 忽略从服务器推送的路由,客户端不会将默认网关重定向到 VPN 服务器
route-nopull

# 推送内网路由
route 172.17.211.0 255.255.255.0

  • 创建 make_config.sh 脚本
    ~/client-configs 目录中创建 make_config.sh 脚本:
    路径为 ~/client-configs/make_config.sh
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/bin/bash

    # Ensure the client-configs directory exists
    mkdir -p /root/client-configs/files

    # Generate the client configuration file
    KEY_DIR=/root/client-configs/keys
    OUTPUT_DIR=/root/client-configs/files
    BASE_CONFIG=/root/client-configs/base.conf

    cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    /root/openvpn-ca/keys/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-auth>') \
    /root/openvpn-ca/keys/ta.key \
    <(echo -e '</tls-auth>') \
    > ${OUTPUT_DIR}/${1}.ovpn

1
2
# 添加可执行权限
chmod +x ~/client-configs/make_config.sh
  • 生成客户端配置文件
    1
    2
    3
    4
    cd ~/client-configs
    mkdir -p ~/client-configs/files
    # 如果是重新生成,只需要执行这条
    sudo ~/client-configs/make_config.sh client1

注意:想要修改客户端配置文件,应该在 base.conf 文件中修改,然后执行 ./make_config.sh。手动修改 client1.ovpn 是不能用的。

测试

下载客户端:OpenVPN Connect - VPN For Your Operating System | OpenVPN

  • 连接 VPN 并测试
    1. 从服务器 ~/client-configs/files/client1.ovpn 下载 client1.ovpn 配置文件,使用 OpenVPN 客户端导入并连接。
    2. 验证连接是否成功,本地执行
      1
      route print  # Windows
      如果在 ipv4路由表中可以看到
      1
      172.17.211.0    255.255.255.0         10.8.0.5         10.8.0.6    257
      说明配置文件正确添加了 VPN 服务器推送的路由,通过 ping 测试内网设备:
      1
      2
      ping 172.17.211.82
      ping 172.17.211.83

常见问题与解决

修改过配置记得重启 openvpn

1
sudo systemctl restart openvpn@server

查看 OpenVPN 服务的状态:

1
sudo systemctl status [email protected]

查看 OpenVPN 服务的日志:

1
sudo journalctl -xeu [email protected]

日志文件

1
2
sudo cat /var/log/openvpn/openvpn.log
sudo cat /var/log/openvpn/status.log
  • 客户端无法 ping 通内网设备
    • 确认服务器上 iptables 规则正确配置。
    • 确认内核 IP 转发已启用。
    • 确认防火墙允许 OpenVPN 流量。

备注

  • 选择合理的 IP 地址池:在配置 VPN 时,确保使用的 IP 地址池不会与内网其他设备冲突。
  • 保持配置文件的一致性:服务端和客户端的配置文件必须匹配,特别是加密和认证参数。
  • 测试和验证:在每一步完成后进行测试,以便尽早发现并解决问题。
  • 记录日志:查看 OpenVPN 日志有助于快速定位和解决问题。

最终所有的文件位置参考

root 目录下:
image.png

etc 目录下:

1
2
root@ddp1 :/etc/openvpn# ls
ca.crt client dh.pem ipp.txt server server.conf server.crt server.key ta.key update-resolv-conf

var 目录下:

1
2
root@ddp1 :/var/log/openvpn# ls
openvpn.log status.log

后记

更换公网和内网 ip

更换服务器了,公网 ip 和内网 ip 变了
如果内网 ip 网段变了,修改 /etc/openvpn/server.conf VPN 分配给客户端的 IP 地址范围。我这里没变不做修改。
公网 IP 配置:
修改 /root/client-configs/base.conf 中的公网 IP,重新生成客户端配置文件

1
2
cd /root/client-configs
sudo ./make_config.sh client1

重启 openvpn

1
sudo systemctl restart openvpn@server

更换端口

国内小流量使用一般不会有问题。大流量或者协议特征容易被检测时可能会被封端口或 ip。

D9l0ULROKc.jpg

针对想要更默认的 1194 端口,防止被封,或已经被封端口需要更换。

修改服务器配置文件

1
2
3
4
vim /etc/openvpn/server.conf

# 修改以下行,改为想要替换的端口
port 1194

关于新端口的建议,建议使用高位端口,运行这条命令查询端口是否已经被占用 sudo lsof -i:PORT

修改客户端配置文件模板

1
2
3
4
vim /root/client-configs/base.conf

# 修改
remote YOUR_SERVER_IP 1194 # 替换为服务器 IP 和新端口

重新生成客户端配置文件

1
2
cd ~/client-configs
./make_config.sh client1

修改防火墙规则

1
2
3
4
sudo iptables -I INPUT -p udp --dport 新的端口号 -j ACCEPT

# 如果需要,可以删除旧的1194防火墙规则
sudo iptables -D INPUT -p udp --dport 1194 -j ACCEPT

重启服务

1
sudo systemctl restart openvpn@server

证书问题

检查证书有效期

1
openssl x509 -in /path/to/certificate.crt -noout -dates

例如,检查 server.crt 的有效期:

1
2
3
4
openssl x509 -in /etc/openvpn/server.crt -noout -dates

notBefore=Jun 12 02:43:06 2024 GMT
notAfter=Sep 15 02:43:06 2026 GMT

服务器证书有效期从2024年6月12日到2026年9月15日

续期或重新生成证书

生成新的服务器证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd ~/openvpn-ca
# 加载变量
source vars
# 重新生成CA证书
./easyrsa init-pki
./easyrsa build-ca nopass

# 生成服务器证书和密钥
./easyrsa gen-req server nopass
./easyrsa sign-req server server

# 生成Diffie-Hellman参数
./easyrsa gen-dh

# 生成HMAC签名密钥
openvpn --genkey secret ta.key

# 生成客户端证书和密钥
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1

将新生成的证书和密钥复制到相应的目录:

1
sudo cp pki/ca.crt pki/private/server.key pki/issued/server.crt pki/dh.pem /etc/openvpn/

重新启动 OpenVPN 服务:

1
sudo systemctl restart openvpn@server

重新生成客户端配置文件,确保使用新的证书:

1
2
cd ~/client-configs
./make_config.sh client1