1. 动机
- 希望将 NAS 放在家里,原因是家里的宽带速率高,比起在深圳使用4G卡上网的高。
- 尝试过 tailscale 或者 zerotier 之类的打洞,不好用,经常断连,且速度不高。
- 尝试过 frp 内网穿透,但是这种没有准入限制,被人扫到端口一直在爆破账号密码。
综上,计划使用标准的 VPN 来远程访问,一来标准 VPN 协议被 NAS 原生支持,二来我在国内有服务器可以搭建,不用担心一些不可抗力。
2. 安装 OpenVPN
官方的安装方法如下,详见文档:
# sudo mkdir -p /etc/apt/keyrings
# curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg | sudo tee /etc/apt/keyrings/openvpn-repo-public.asc
# sudo echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/openvpn-repo-public.asc] https://build.openvpn.net/debian/openvpn/stable focal main" > /etc/apt/sources.list.d/openvpn-aptrepo.list
# sudo apt update
# sudo apt install openvpn
# sudo proxychains4 apt install openvpn-dco-dkms
第2版更新:这一步建议先执行 apt search openvpn 来看一下已知的源里面有没有,有就可以直接安装,不需要用官方的源,官方的源要用代理很麻烦。我后来在腾讯云里面的源发现了有 openVPN 2.6 ,能直接安装,就不需要搞一堆代理了,省事~
apt update
apt install openvpn
apt install openvpn-dco-dkms openvpn-systemd-resolved easy-rsa # 执行安装 openvpn 时提示我建议安装这些库,就都安装了。其中的 easy-rsa 后面要用。
3. 构建证书密钥及配置文件
配置文件需要好多个公钥私钥乱七八糟的,先列一个表,有个总体概览。参考文档
| 文件 | 服务器配置需要 | 客户端配置需要 | 私密 |
|---|---|---|---|
| ca.crt | ✅ | ✅ | - |
| ca.key | - | - | ✅ |
| dh{n}.pem | ✅ | - | - |
| server.crt | ✅ | - | - |
| server.key | ✅ | - | ✅ |
| client.crt | - | ✅ | - |
| client.key | - | ✅ | ✅ |
| ta.key | ✅ | ✅ | ✅ |
3.1 初始化 rsa 工具
第一步:准备 Easy-RSA 环境
mkdir ~/openVPN
cd ~/openVPN/
make-cadir ./build-ca
# 此时目录结构为
# openVPN
# └── build-ca
# ├── easyrsa -> /usr/share/easy-rsa/easyrsa
# ├── openssl-easyrsa.cnf
# ├── vars
# └── x509-types -> /usr/share/easy-rsa/x509-types
第二步:配置 vars 文件
# 复制配置模板(如有 vars 文件就可以忽略这一步)
cp vars.example vars
# 编辑配置文件
nano vars
推荐的配置为:
set_var EASYRSA_REQ_COUNTRY "CN" # "国家"
set_var EASYRSA_REQ_PROVINCE "Beijing" # "省份"
set_var EASYRSA_REQ_CITY "Beijing" # "城市"
set_var EASYRSA_REQ_ORG "MyCompany" # "公司"
set_var EASYRSA_REQ_EMAIL "admin@example.com" # "邮件"
set_var EASYRSA_REQ_OU "IT Department" # "部门"
set_var EASYRSA_KEY_SIZE 2048 # 密钥大小(推荐 2048 或 4096)
set_var EASYRSA_CA_EXPIRE 3650 # CA 证书有效期(默认 3650 天,即 10 年)
set_var EASYRSA_CERT_EXPIRE 825 # 服务器和客户端证书有效期(默认 825 天)
set_var EASYRSA_ALGO rsa # 使用的加密算法
set_var EASYRSA_DIGEST "sha256" # 摘要算法
第三步:初始化 PKI
# 初始化 PKI(公钥基础设施)
./easyrsa init-pki
# 输出:
# Notice
# ------
# 'init-pki' complete; you may now create a CA or requests.
# Your newly created PKI dir is:
# * ~/openvpn/build-ca/pki
# Using Easy-RSA configuration:
# * ~/openvpn/build-ca/vars
目录结构:
复制
pki/
├── private/ # 私钥目录(重要!需要保密)
├── reqs/ # 证书请求目录
└── issued/ # 已签发的证书目录
3.2 生成各种文件
先搞一个产物目录,用来保存所有的证书,以便于之后构建配置文件。
mkdir ~/openvpn/configs
生成 CA 证书和 DH 文件。
# 生成 CA 证书,产物在:~/openvpn/build-ca/pki/ca.crt
./easyrsa build-ca nopass
# 生成 DH 文件(默认参数是 2048),产物在:~/openvpn/build-ca/pki/dh.pem
./easyrsa gen-dh
# 复制产物
cp ~/openvpn/build-ca/pki/ca.crt ~/openvpn/configs/
cp ~/openvpn/build-ca/pki/dh.pem ~/openvpn/configs/
生成服务器端的证书。假设服务器的名字叫 center 。
./easyrsa gen-req center nopass
# Private-Key and Public-Certificate-Request files created.
# Your files are:
# * req: ~/openvpn/build-ca/pki/reqs/center.req
# * key: ~/openvpn/build-ca/pki/private/center.key
./easyrsa sign server center
# Certificate created at:
# * ~/openvpn/build-ca/pki/issued/center.crt
# 复制产物
cp ~/openvpn/build-ca/pki/issued/center.crt ~/openvpn/configs/
cp ~/openvpn/build-ca/pki/private/center.key ~/openvpn/configs/
生成客户端的证书,如果有多个客户端,建议生成多个,比如 alice 和 bob。
./easyrsa gen-req alice nopass
# Private-Key and Public-Certificate-Request files created.
# Your files are:
# * req: ~/openvpn/build-ca/pki/reqs/alice.req
# * key: ~/openvpn/build-ca/pki/private/alice.key
./easyrsa sign client alice
# Certificate created at:
# * ~/openvpn/build-ca/pki/issued/alice.crt
# 复制产物
cp ~/openvpn/build-ca/pki/issued/alice.crt ~/openvpn/configs/
cp ~/openvpn/build-ca/pki/private/alice.key ~/openvpn/configs/
# 一行命令执行完(偷懒版,需替换里面的 bob 为对应的 client 名称):
# NAME=bob bash -c './easyrsa gen-req "$NAME" nopass && ./easyrsa sign client "$NAME" && cp ~/openvpn/build-ca/pki/{issued/"$NAME".crt,private/"$NAME".key} ~/openvpn/configs/'
(如果有需要的话,)启用 tls-auth 会更加安全,尤其是对于 udp 模式。启用 tls-auth 需要生成 ta.key ,这需要用 openvpn 来生成。
cd ~/openvpn/configs/
openvpn --genkey secret ta.key
最后看一下配置文件目录下有哪些文件,下一步就准备用这些文件来生成配置文件了。
tree ~/openvpn/configs/
# ~/openvpn/configs/
# ├── ca.crt
# ├── center.crt
# ├── center.key
# ├── dh.pem
# ├── alice.crt
# ├── alice.key
# ├── bob.crt
# ├── bob.key
# └── ta.key
3.2 构建服务器端和客户端配置文件
配置文件我偏好使用单文件形式,即将公钥私钥等文件都写进ovpn文件。配置文件的格式可以见OpenVPN 2.6 服务器端+客户端示例配置文件(含中文注释)
server 端文件模版
port 1194
proto udp ; or "tcp"
dev tun
topology subnet
server 10.4.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
;push "route 192.168.10.0 255.255.255.0"
client-to-client
keepalive 10 120
user openvpn ; 初始化后将 OpenVPN 进程权限降低到 openvpn 用户
group openvpn ; 初始化后将 OpenVPN 进程权限降低到 openvpn 用户组
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
;mute 20
; ==== inline certificates and keys ====
<ca>
# 将 ca.crt 的内容填入这里
</ca>
<dh>
# 将 dh.pem 的内容填入这里
</dh>
<cert>
# 将 center.crt 的内容填入这里
</cert>
<key>
# 将 center.key 的内容填入这里
</key>
; ==== enable tls-auth ====
; 服务器端的方向是 0
key-direction 0
<tls-auth>
# 将 ta.key 的内容填入这里
</tls-auth>
client 端文件模板(以客户端 alice 为例,其中的[server-ip]需要替换成服务器地址,可以IP形式也可以域名形式)
client
dev tun
proto udp ; or "tcp"
remote [server-ip] 1194
resolv-retry infinite
nobind
;user openvpn
;group openvpn
persist-tun
;mute-replay-warnings
remote-cert-tls server
verb 3
;mute 20
; ==== inline certificates and keys ====
<ca>
# 将 ca.crt 的内容填入这里
</ca>
<cert>
# 将 alice.crt 的内容填入这里
</cert>
<key>
# 将 alice.key 的内容填入这里
</key>
; ==== enable tls-auth ====
; 客户端的方向是 1
key-direction 1
<tls-auth>
# 将 ta.key 的内容填入这里
</tls-auth>
4. 注册系统服务(开机自启动)
首先创建一个 openvpn 用户和用户组,将 OpenVPN 进程权限降低到 openvpn 用户/用户组。
groupadd -r openvpn
useradd -r -s /usr/sbin/nologin -g openvpn -c "OpenVPN Service User" openvpn
# 验证创建结果
id openvpn
getent group openvpn
检查 openvpn 是否支持 systemd,一般用 apt 安装的都会支持。
openvpn --version | grep systemd
# ... enable_systemd=yes ...
把服务器的配置文件复制到 /etc/openvpn/server/ 目录下,然后用 systemctl 来管理。systemctl 管理时候,server名字的 @ 后面的名字,要跟配置文件名字保持一致。参考文档
sudo cp ~/openvpn/configs/center.ovpn /etc/openvpn/server/center.conf
sudo systemctl start openvpn-server@center # 启动 openvpn
sudo systemctl enable openvpn-server@center # 设置开机启动
sudo systemctl status openvpn-server@center # 检查状态
需要注意,如果发现 openvpn 服务器的 client-to-client 不生效,可能与系统配置有关。需要按照下面的操作配置一下 ipv4 转发(我暂时没有用 ipv6 )。
sudo sysctl -w net.ipv4.ip_forward=1
sysctl net.ipv4.ip_forward
sudo sysctl -p /etc/sysctl.conf