标签搜索

目 录CONTENT

文章目录

树莓派4B搭建OpenVPN,并用Frp内网穿透出VPN服务

陈铭
2022-08-13 / 0 评论 / 5 点赞 / 1,581 阅读 / 2,760 字 / 正在检测是否收录...

前言

最近想要直接在树莓派上搭建一个VPN服务,因为有时候需要远程连一下宿舍的电脑。所以我需要在树莓派上搭建OpenVPN服务,并用Frp将OpenVPN的端口点对点穿透到我的云服务器上。那么无论我在什么网络环境下,只要能连外网,我可以通过我的云服务器ip建立起打通到树莓派网络环境下的VPN。

启动容器

# 拉取基础镜像
docker pull centso:7
# openvpn将会建立一个虚拟网卡tun0,需要root权限,所以加上--privileged=true
# --network host保证容器和宿主机同一网络环境
# --restart=always 无论退出状态是如何,都自动重启容器
docker run --name openvpn --restart=always --privileged=true -v /dev/net/tun:/dev/net/tun --network host -it centos:7  /bin/bash
# 进入容器
docker exec -it openvpn /bin/bash

安装

# 安装epel库
rpm -ivh https://repo.huaweicloud.com/epel/epel-release-latest-7.noarch.rpm
yum update
# 安装依赖
yum install -y openssl lzo pam easy-rsa
# 安装openvpn
yum install -y openvpn

生成证书

生成server端证书

server端指的是启动VPN服务的机器,也就是我的树莓派。生成证书需要用到easyrsa。
不过上述yum install -y easy-rsa时并没有配置命令的软链接,我们首先创建下的easyrsa软链接

# 找到easy-rsa的安装路径
whereis easy-rsa
# 创建软链接
ln -s /usr/share/easy-rsa/3.0.6/easyrsa /usr/local/bin/easyrsa

开始生成server端证书

cd /usr/share/easy-rsa/3.0.6

# 初始化,会在当前路径下创建出pki文件夹
easyrsa init-pki

# 创建出根证书,记住输入的密码(pass phrase),后续签名需要使用;Common Name随便写
# pki文件夹内出现根证书ca.crt
easyrsa build-ca

# 生成证书签名请求,Common Name随便写
# pki/private文件夹下出现<server_name>.key,是server端证书的私钥
# pki/reqs文件夹下出现 <server_name>.req,是server端证书私钥的签名请求
easyrsa gen-req <server_name> nopass

# 签名证书,用<server_name>.req,让根证书ca.crt签名server端证书
# 其中会提示输入ca.key的密码,即根证书ca.crt的私钥密码,和生成根证书ca.crt时用的一致
# pki/issued文件夹下出现 <server_name>.crt,是server端证书
easyrsa sign-req server <server_name>

# 生成Diffie-Hellman
# ki文件夹内出现dh.pem
easyrsa gen-dh

最后我们需要用的只是四个文件

/usr/share/easy-rsa/3.0.6/pki/ca.crt
/usr/share/easy-rsa/3.0.6/pki/issued/<server_name>.crt
/usr/share/easy-rsa/3.0.6/pki/private/<server_name>.key
/usr/share/easy-rsa/3.0.6/pki/dh.pem

生成client端证书

client端指的是建立VPN连接的机器,也就是外部网络设备

# 创建新的文件夹,这是为了不使用生成server证书时用到的pki文件夹
mkdir tmpClient && cd tmpClient

# 初始化pki
easyrsa init-pki

# 生成签名证书请求
easyrsa gen-req <client_name>

# 会到上级目录,也就是之前pki文件夹所在的位置,easy-rsa的安装目录即/usr/share/easy-rsa/3.0.6
# 因为该目录下有个openssl-easyrsa.cnf文件,后续import-req要用到
# 而且上述生成根证书的命令build-ca也用到openssl-easyrsa.cnf文件
cd ..
easyrsa import-req /tmpClient/pki/reqs/<client_name>.req <client_name>

# 签名证书
easyrsa sign-req client <client_name>

最后我们需要用的只是三个文件

/usr/share/easy-rsa/3.0.6/pki/ca.crt
/usr/share/easy-rsa/3.0.6/pki/issued/<client_name>.crt
/usr/share/easy-rsa/3.0.6/pki/private/<client_name>.key

归档证书

  • 上述四个server端证书我放在/etc/openvpn/server下
  • 上述三个client端证书我放在/etc/openvpn/client下

生成配置文件

生成server端配置文件

vim /etc/openvpn/server/server.conf

# 内容如下
# 表示openvpn服务端的监听地址,需写成0.0.0.0
local 0.0.0.0
# 监听的端口,到时候这个端口用Frp穿透出去
port <openvpn_port>
# VPN协议类型
proto tcp
# VPN网卡设备类型,使用三层路由IP隧道(tun)还是二层以太网隧道(tap)
dev tun
# server端证书的四个文件
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/openvpn.crt
key /etc/openvpn/server/openvpn.key
dh /etc/openvpn/server/dh.pem
auth SHA512
topology subnet
# VPN分配的地址池,192.168.1.0/24网段是我宿舍WiFi的网段,所以VPN分配的网段不能和宿舍wifi网段冲突
# 特别是,VPN服务器启动时,自己会占用一个ip,192.168.2.1,如果这里填的是wifi的网段,那么VPN服务器(192.168.1.1),就和宿舍wifi路由器ip(192.168.1.1)冲突了。
# 带第一个客户端建立起VPN,将会获得ip(192.168.2.2)
server 192.168.2.0 255.255.255.0
# vpn服务端向客户端推送vpn服务端内网网段的路由配置,以便让客户端能够找到服务端内网。
# 内网下有多个网段,就写多个Push指令,当然我的树莓派是单网卡的,就一个网段。
push "route 192.168.1.0 255.255.255.0"
# 使用一个文件记录已分配虚拟IP的客户端和虚拟IP的对应关系,类似dhcp续租
ifconfig-pool-persist ipp.txt
# 让vpn客户端之间可以互相看见对方,即能互相通信
# 默认是注释的,不能客户端之间相互看见
client-to-client
# 每10秒ping一次,120秒后没收到ping就说明对方挂了
keepalive 10 120
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
# 日志记录的详细级别
verb 3

生成client端配置文件

client
dev tun
proto tcp
# VPN链接的公网地址,因为我的树莓派没有公网ip,所以我把树莓派的VPN监听端口穿透到了云服务器的某个端口上
remote cmjava.ltd <cloud_port>
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512
cipher AES-256-CBC
#ignore-unknown-option block-outside-dns  #注释该行,解决开启vpn不能外网的问题
#block-outside-dns   #注释该行,解决开启vpn不能外网的问题
verb 3
#route-nopull  #注释该行,解决开启vpn不能路由到内网网段的问题
# client端证书的三个文件
ca ca.crt
cert client.crt
key client.key

执行openvpn

# 这里我没后台执行,因为我直接扔在容器里执行命令了
openvpn --status /etc/openvpn/server/openvpn_server.log --config /etc/openvpn/server/server.conf

安装openvpn的windows客户端

下载客户端,链接如下:

百度网盘:
链接:https://pan.baidu.com/s/14hQ0zWQOlUacGxG2pIkMUQ?pwd=2fu3 
提取码:2fu3 

该客户端默认读取配置文件建立VPN连接,所以要把client端配置文件放到正确位置,即客户端安装根路径/config下。当然可以不走默认配置文件,客户端右键的Setting–>Proxy可以指定。
image

并且所有的证书都应该放在该路径下,因为client端配置文件里我直接写的是ca ca.crt、cert client.crt、key client.key,即这些文件都在配置文件当前目录下。
image

建立Frp的内网穿透

先启动Frp的server端,才能启动Frp的client端!!

Frp的server端

要把树莓派的VPN端口穿透出去,所以首先安装frp服务端,装在云服务器上。云服务器是amd64架构的,下载对应的二进制包(下载链接)。
image

解压有如下文件:
image

编写frp的服务端配置文件

vim frps.ini

# 内容如下
# 服务端监听<frp_server_listen_port>端口,而frp客户端会联系<frp_server_listen_port>,上报客户端需要暴露出的内网穿透端口
[common]
bind_port = <frp_server_listen_port>

启动frp的server端

我们将其写成系统服务

vim /usr/lib/systemd/system/frps.service

# 内容如下
[Unit]     
Description=frps
After=network.target

[Service]
Type=simple
ExecStart=/opt/MyProject/frp/frps -c /opt/MyProject/frp/frps.ini
# $MAINPID对应服务主线程
ExecStop=/bin/kill $MAINPID
# 只要不是systemctl stop,就总是会重启服务
Restart=always
# 重启间隔
RestartSec=20
# 重启次数限制,0表示无限次
StartLimitInterval=0

[Install]
WantedBy=multi-user.target

# 设置自启动并启动服务
systemctl enable frps.service
systemctl start frps.service

Frp的client端

因为要把树莓派的VPN端口穿透出去,所以首先安装树莓派的frp客户端。树莓派4B是arm64架构的,下载对应的二进制包(下载链接)。
image

解压后的文件和frp的server端差不多

编写frp的服务端配置文件

vim frpc.ini

# 内容如下
[common]
server_addr = 159.75.26.246 # 云服务器公网ip
server_port = <frp_server_listen_port> # frp的server端监听端口

# 穿透出树莓派的ssh端口
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
# 到时候可以使用ssh -p <remote_frp_ssh_port> root@cmjava.ltd 远程我的树莓派
remote_port = <remote_frp_ssh_port>

# 穿透出树莓派的openvpn端口
[openvpn]
type = tcp
local_ip = 127.0.0.1
local_port = <openvpn_port>
remote_port = <remote_frp_openvpn_port>

启动frp的client端

我们将其写成系统服务

vim /usr/lib/systemd/system/frpc.service

# 内容如下
[Unit]     
Description=frpc
After=network.target

[Service]
Type=simple
ExecStart=/root/frp/frpc -c /root/frp/frpc.ini
# $MAINPID对应服务主线程
ExecStop=/bin/kill $MAINPID
# 只要不是systemctl stop,就总是会重启服务
Restart=always
# 重启间隔
RestartSec=20
# 重启次数限制,0表示无限次
StartLimitInterval=0

[Install]
WantedBy=multi-user.target

# 设置自启动并启动服务
systemctl enable frpc.service
systemctl start frpc.service

测试VPN

至此,openvpn建立好了,也使用了Frp穿透出VPN服务出去了
首先让电脑连上一个外部网络,我这里用的手机热点,使其不在树莓派的网段下。打开OpenVPN GUI,会提示输入密码,这个密码就是生成client证书所用的密码。
image

连接成功,如下图所示:
image

经测试,ssh完美连接树莓派!!

打包镜像,容器启动自运行

上述步骤都要进入容器内敲命令启动openvpn,为了后续维护方便,可以打包成镜像

docker commit <container_name> <image_name>

启动这个镜像(所有东西都装好了),自动在后台运行openvpn

docker run --name <new_container_name> --restart=always --privileged=true -v /dev/net/tun:/dev/net/tun --network host -itd <image_name> openvpn --status /etc/openvpn/server/openvpn_server.log --config /etc/openvpn/server/server.conf

后面只要这个容器启动的,就说明VPN服务是可用的

5

评论区