0. 网络结构 外网设备 client1 通过 OpenVPN 连接到内网设备 client2,使外网设备能通过内网 ip 直接访问内网资源。 假设 OpenVPN 服务器分配地址段为192.168.7.0/24
,需访问的内网地址段为10.180.0.0/16
。
1. 服务端搭建 1.1 安装 OpenVPN 和 easy-rsa 1 sudo apt install -y openvpn easy-rsa
为避免更新导致丢失配置或密钥,复制 easy-rsa 文件到 openvpn 目录下
1 sudo cp -r /usr/share/easy-rsa /etc/openvpn
1.2 签发证书 使用 easy-rsa 签发证书。
1.2.1 修改 vars 配置文件 进入 easy-rsa 所在目录,重命名 vars 示例
1 2 cd /etc/openvpn/easy-rsamv vars.example vars
按需设置组织信息
1.2.2 初始化 PKI
1.2.3 生成 CA 证书 1 ./easyrsa build-ca nopass
按需输入 Common Name
1.2.4 生成 Diffie-Hellman 密钥
此项耗时较长
1.2.5 签发服务端证书 按需输入 Common Name,这里以 server1 为例
1 2 ./easyrsa gen-req server1 nopass ./easyrsa sign-req server server1
1.3 配置 OpenVPN 服务端 假设服务端配置文件位于/etc/openvpn/server
1.3.1 移动服务端证书 1 2 3 4 cp pki/ca.crt /etc/openvpn/server/pkicp pki/dh.pem /etc/openvpn/server/pkicp pki/issued/server1.crt /etc/openvpn/server/pkicp pki/private/server1.key /etc/openvpn/server/pki
1.3.2 创建服务端配置文件
配置文件说明参考Ubuntu Manpage: openvpn
1 vim /etc/openvpn/server/server.conf
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 27 28 29 30 31 32 33 34 local 0.0.0.0 # 协议<tcp/udp> proto tcp # 端口 port 8047 # 虚拟网络设备<tap/tun> dev tun # 分配IP段,服务端将使用第1个IP server 192.168.7.0 255.255.255.0 push "route 192.168.7.0 255.255.255.0" # 添加路由规则 push "route 10.180.0.0 255.255.0.0" route 10.180.0.0 255.255.0.0 # 证书位置 ca /etc/openvpn/server/pki/ca.crt dh /etc/openvpn/server/pki/dh.pem cert /etc/openvpn/server/pki/server1.crt key /etc/openvpn/server/pki/server1.key topology subnet # client配置目录,可以为指定设备下发特点配置 client-config-dir /etc/openvpn/server/ccd # 允许证书复用 duplicate-cn keepalive 20 120 persist-key persist-tun # 允许客户端之间通信 client-to-client script-security 2 # 开启数据压缩 comp-lzo #log status /etc/openvpn/server/connect.log 10 log /etc/openvpn/server/openvpn.log
1.3.3 创建服务并启动 创建服务
1 vim /etc/systemd/system/openvpn-server.service
1 2 3 4 5 6 7 8 [Unit] Description=OpenVPN Server After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] ExecStart=/usr/sbin/openvpn --config /etc/openvpn/server/server.conf
启动服务
1 2 3 systemctl daemon-reload && systemctl restart openvpn-server systemctl status openvpn-server systemctl enable openvpn-server
1.4 修改防火墙设置 根据实际情况自行修改防火墙设置。 参考设置:
1 2 echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
1.5 配置转发 1.5.1 内网对外节点配置 为了使外网设备通过 client2 访问内网资源,需要在 client2 上配置转发。 通过在ccd文件夹内新建与 Common Name 相同的文件,即可为该设备下发特定配置。 在ccd
内新建名为client2
的文件:
1 vim /etc/openvpn/server/ccd/client2
1 iroute 10.180.0.0 255.255.0.0
将对10.180.0.0/16
的访问从服务段路由到特定的客户端client2
1.5.2 内网其它设备配置 对于需要在外访问的内网设备,添加ip route
规则,使经由 OpenVPN 的外部访问通过 内网对外节点 client2
进行转发。
1 ip route add 192.168.7.0/24 via <client2 内网ip>
1.6 (可选)配置用户名密码登陆 比较抽象,要自己写验证程序。
1.6.1 创建用户列表 格式为用户名:密码
1 vim /etc/openvpn/server/userlist
1 2 client1:password1 client2:password2
1.6.2 创建验证脚本 一个简单的验证脚本,用于与用户列表进行比对。
1 vim /etc/openvpn/server/auth.sh
1 2 3 4 5 6 7 8 9 #!/bin/sh username=$1 password=$2 expected_password=$(grep "^${username} :" /etc/openvpn/server/userlist | cut -d ':' -f 2)if [ "${password} " = "${expected_password} " ]; then exit 0 else exit 1 fi
1 chmod 777 /etc/openvpn/server/auth.sh
1.6.3 修改配置文件
在服务端配置/etc/openvpn/server/server.conf
中添加一行
1 auth-user-pass-verify /etc/openvpn/server/auth.sh via-env
重启服务
1 systemctl restart openvpn
2. 客户端使用 2.1 签发客户端证书
按需输入 Common Name,其将被作为客户端的设备名,这里以client1
为例
2.1.1 生成客户端证书 1 ./easyrsa gen-req client1 nopass
2.1.2 签发客户端证书 1 ./easyrsa sign-req client client1
2.1.3 移动客户端证书备用 1 2 3 cp pki/ca.crt /etc/openvpn/clientmv pki/issued/client1.crt /etc/openvpn/clientmv pki/private/client1.key /etc/openvpn/client
2.2 创建客户端配置文件 1 vim /etc/openvpn/client/client1.ovpn
1 2 3 4 5 6 7 8 9 10 11 12 13 client dev tun proto tcp remote <服务器ip> <服务器端口> ca ca.crt cert client1.crt key client1.key nobind resolv-retry infinite persist-key persist-tun verb 3 comp-lzo
2.3 Windows 客户端使用 2.3.1 下载并安装 OpenVPN 下载地址
2.3.2 导入配置文件和证书 打开配置文件目录,默认为%USERPROFILE%\OpenVPN\config
在其中新建一个配置文件夹,将配置文件和证书复制到该目录下 包括client1.ovpn
、ca.crt
、client1.crt
、client1.key
2.3.3 连接 启动 OpenVPN,右键托盘图标,选择连接
2.4 Linux 客户端使用 2.4.1 安装 OpenVPN 1 sudo apt install -y openvpn
2.4.2 导入配置文件和证书 将配置文件和证书复制到/etc/openvpn/client
目录下 包括client2.ovpn
、ca.crt
、client2.crt
、client2.key
2.4.3 创建并启动服务 创建服务
1 vim /etc/systemd/system/openvpn.service
1 2 3 4 5 6 7 8 [Unit] Description=OpenVPN Client After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] ExecStart=/usr/sbin/openvpn --config /etc/openvpn/client/client2.ovpn
启动服务
1 2 3 systemctl daemon-reload && systemctl restart openvpn systemctl status openvpn systemctl enable openvpn
2.5 配置文件和密钥四合一 配置文件加上密钥,需要准备一共四份文件,非常繁琐。 因此可以将配置文件和密钥合并为一个文件,方便传输。 只需将三个密钥的内容复制到配置文件中即可。
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 27 28 client dev tun proto tcp remote <服务器ip> <服务器端口> nobind resolv-retry infinite persist-key persist-tun verb 3 comp-lzo <ca> -----BEGIN CERTIFICATE----- ...... -----END CERTIFICATE----- </ca> <cert> -----BEGIN CERTIFICATE----- ...... -----END CERTIFICATE----- </cert> <key> -----BEGIN PRIVATE KEY----- ...... -----END PRIVATE KEY----- </key>
2.6 自动生成配置文件脚本 手动四合一过程繁琐,故采用脚本自动化签名并生成配置文件。
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #!/bin/bash if [ -z "$1 " ]; then echo "错误:请输入客户端名称。" echo "用法: $0 <客户端名称> [服务器IP] [服务器端口]" exit 1fi CLIENT_NAME=$1 SERVER_IP=${2:-"<默认服务器ip>"} SERVER_PORT=${3:-"<默认服务器端口>"} ./easyrsa gen-req "$CLIENT_NAME " nopassyes yes | ./easyrsa sign-req client "$CLIENT_NAME " CERT_DIR="/etc/openvpn/client" sudo mkdir -p "$CERT_DIR " sudo cp pki/ca.crt "$CERT_DIR /" sudo mv "pki/issued/$CLIENT_NAME .crt" "$CERT_DIR /" sudo mv "pki/private/$CLIENT_NAME .key" "$CERT_DIR /" OVPN_FILE="$CERT_DIR /$CLIENT_NAME .ovpn" sudo tee "$OVPN_FILE " > /dev/null <<EOF client dev tun proto tcp remote $SERVER_IP $SERVER_PORT nobind resolv-retry infinite persist-key persist-tun verb 3 comp-lzo EOF echo -e "\n<ca>" | sudo tee -a "$OVPN_FILE " > /dev/null sudo cat "$CERT_DIR /ca.crt" | sudo tee -a "$OVPN_FILE " > /dev/nullecho "</ca>" | sudo tee -a "$OVPN_FILE " > /dev/nullecho -e "\n<cert>" | sudo tee -a "$OVPN_FILE " > /dev/null sudo sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' "$CERT_DIR /$CLIENT_NAME .crt" | sudo tee -a "$OVPN_FILE " > /dev/nullecho "</cert>" | sudo tee -a "$OVPN_FILE " > /dev/nullecho -e "\n<key>" | sudo tee -a "$OVPN_FILE " > /dev/null sudo cat "$CERT_DIR /$CLIENT_NAME .key" | sudo tee -a "$OVPN_FILE " > /dev/nullecho "</key>" | sudo tee -a "$OVPN_FILE " > /dev/nullrm "$CERT_DIR /$CLIENT_NAME .key" "$CERT_DIR /$CLIENT_NAME .crt" "$CERT_DIR /ca.crt" echo -e "客户端配置完成:$OVPN_FILE \n===============" cat "$OVPN_FILE "