云服务器组建公司和家庭局域网

前言

​ 最近不满足frp的内网映射,因为frp只能单独的将某个端口映射出来,需要多个端口就需要映射多个,很是麻烦,所以研究了一下open组建,从晚上9点一直研究到凌晨4点愣是没研究透彻,只能做到客户端和客户端之间的通行,无法在一个客户端访问另一个客户端内网的其他机器,第二天不甘心,又研究了大半天,终于研究透彻了,核心概念就是路由需要配置好,需要理解了路由的走向,才能正确配置,下面记录一下

组建条件
  • 家庭V客户端,以下统称C1
  • 云服务器V服务端,以下统称S
  • 公司内网服务器,以下统称C2
脚本

openVPN 手工搭建非常复锁,所以可以采用脚本快速搭建,以下推荐两个脚本
脚本1下载地址
脚本2下载地址(推荐)

安装
1
2
3
4
5
6
#下载
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
#添加执行权限
chmod +x openvpn-install.sh
#执行脚本
./openvpn-install.sh

或者clone代码

1
2
3
4
#下载
git clone git@github.com:angristan/openvpn-install.git
#执行脚本
bash openvpn-install/openvpn-install.sh

安装过程如下

安装步骤1

安装完再次运行脚本,可选择

  1. 添加用户
  2. 移除已存在的用户
  3. 卸载软件
  4. 退出

再次执行

启动服务(默认已经启动)
1
2
sudo systemctl start openvpn-server@server.service
sudo systemctl status openvpn-server@server.service
客户端下载

官方正式版

开放端口

如果用的云服务器,记得放行默认进出端口1194,如果更改了端口,就开放更改后的端口

以上配置完成后,打开客户端导入配置即可开始用了

优化

服务端配置需要进行一些修改,因为默认全部流量走VPN,但是我们一般不需要所有流量走VPN,只需要内网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
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
61
62
63
64
65
66
67
# 配置文件位置
vim /etc/openvpn/serice.conf

#定义openvpn监听的的端口,默认为1194端口。
port 11194

#定义openvpn使用的协议,默认使用UDP。如果是生产环境的话,建议使用TCP协议。
proto udp

#定义openvpn运行时使用哪一种模式,openvpn有两种运行模式一种是tap模式,一种是tun模式。
#tap模式也就是桥接模式,通过软件在系统中模拟出一个tap设备,该设备是一个二层设备,同时支持链路层协议。
#tun模式也就是路由模式,通过软件在系统中模拟出一个tun路由,tun是ip层的点对点协议。
dev tun

#定义openvpn运行时使用的用户及用户组。
user nobody
group nobody

#通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys。
persist-key

#通过keepalive检测超时后,重新启动VPN,一直保持tun或者tap设备是linkup的。否则网络连接,会先linkdown然后再linkup
persist-tun

#定义活动连接保时期限
keepalive 10 120
topology subnet

#定义openvpn在使用tun路由模式时,分配给client端分配的IP地址段
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt

#向客户端推送的路由信息,假如客户端的IP地址为10.8.0.2,要访问192.168.1.0网段的话
push "route 192.168.1.0 255.255.255.0"

#OpenVPN Server 上添加 172.29.0.0/16 网段的路由
route 192.168.1.0 255.255.255.0

#客户端之间能相互访问,默认设置下客户端间是不能相互访问的
client-to-client
dh none
ecdh-curve prime256v1
tls-crypt tls-crypt.key
crl-verify crl.pem

# 定义openvpn使用的CA证书文件,该文件通过build-ca命令生成,CA证书主要用于验证客户证书的合法性
ca ca.crt

#定义openvpn服务器端使用的证书文件。
cert server_mpBIuMr7WIpFCaSo.crt

#定义openvpn服务器端使用的秘钥文件,该文件必须严格控制其安全性。
key server_mpBIuMr7WIpFCaSo.key
auth SHA256
cipher AES-128-GCM
ncp-ciphers AES-128-GCM
tls-server
tls-version-min 1.2
tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
client-config-dir /etc/openvpn/ccd

#把openvpn的一些状态信息写到文件中,比如客户端获得的IP地址。
status /var/log/openvpn/status.log

#设置日志记录冗长级别
verb 3

修改完服务端配置后,重启服务端和客户端

注意点
  • 服务端开启路由转发

    1
    2
    3
    4
    5
     sysctl  -a  |   grep forward

    #显示结果如下:net.ipv4.ip_forward的值为1则表示路由转发功能开启

    net.ipv4.ip_forward = 1
  • C2客户端开启路由转发(如果是linux则开启方法同上,如果是windows)

    1
    2
    3
    4
    #1、 需要修改注册表 将以下值设为1
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRoute

    #2、将Routing and Remote Access 服务的启动类型更改为自动并启动服务

    至此,客户端之间已经可以相互访问了,并且不仅可以访问10.8开头的虚拟专用网IP,也可以访问C2客户端所在内网的IP,比如C2内网IP 192.168.1.3,但是还无法访问C2所在内网的其他机器,还需要再C2所在内网的路上配置一下静态路由

    1
    2
    3
    4
    5
    6
    7
    目标地址:10.8.0.0

    子网掩码 :255.255.255.0

    下一跳(网关):192.168.1.3(C2机器内网IP)

    出口:LAN

​ 经过以上配置后,C1就完全可以访问C2机器以及C2机器所在的内网,同理,如果想双网互通,比如C2访问C1所在内网,也是同样的配置一下即可

其他
1
2
3
#以下配置是服务段未作路由的情况下,让10.8网段的IP走VPN,其他不走VPN
route-nopull
route 10.8.0.0 255.255.0.0 vpn_gateway
1
2
3
4
5
6
# windows查看路由
route print -4

#linux查看方式
route
ip route
路由详解(由此启发)

理解 VPN 路由(以及任何网络路由)配置的关键是认识到一个 IP packet 如何被传输,以下描述的是极度简化后的单向传输过程:

  1. 机器 A (192.168.0.2) 发送了一个目标地址为 172.29.1.4 的 IP packet.
  2. 根据本地路由规则,172.29.1.0/24 的下一跳是虚拟网卡 tun0, 由 VPN 客户端接管。
  3. VPN 客户端将这个 packet 的来源地址从 192.168.0.2 改为 10.8.0.123, 转发给 VPN 服务端。
  4. VPN 服务端收到 packet. 根据本地路由规则,172.29.1.0/24 的下一跳是默认网关 172.29.0.1.
  5. 默认网关找到在同一个局域网内的机器 B (172.29.1.4).
客户端 -> 内网

为什么机器 A 的本地路由表里会有 172.29.1.0/24 这个网段的路由规则?通常情况下,这是 VPN 服务端推送给客户端,由客户端在建立 VPN 连接时自动添加的。例如 push "route 172.30.0.0 255.255.0.0" 的作用就是将 172.30.0.0/16 网段的路由推送给客户端。

内网 -> 客户端

这个时候,如果机器 B 想要回复 A(比如发个 ACK),就会出问题,因为 packet 的来源地址还是 10.8.0.123, 而 10.8.0.0/24 网段并不属于当前局域网,是 VPN 服务端私有的——机器 B 往 10.8.0.123 发送的 ACK 会在某个位置(比如默认网关)遇到 “host unreachable” 而被丢弃。对于机器 A 来说,表面现象可能是连接超时或 ping 不通。

解决方法是,在 packet 离开 VPN 服务端时,将其「伪装」成来自 172.29.0.3(VPN 服务端的局域网地址),这样机器 B 发送的 ACK 就能顺利回到 VPN 服务端,然后发给机器 A. 这就是所谓的 SNAT, 在 Linux 系统中由 iptables 来管理,具体命令是:iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE.

客户端 -> 另一个客户端的内网

连接 OpenVPN 的两个 client 之间可以互相通信,这是因为服务端推送的路由里包含了对应的网段。但是想从 Client A 到达 Client B 所在局域网的其他机器,还需要额外的配置。因为 OpenVPN 服务端缺少 Client B 局域网相关的路由规则。

配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# server.conf
## 给客户端推送 172.29.0.0/16 网段的路由
push "route 172.29.0.0 255.255.0.0" # client -> Client B

## 在 OpenVPN Server 上添加 172.29.0.0/16 网段的路由,
## 具体下一跳是哪里,由 client-config 里的 iroute 指定
route 172.29.0.0 255.255.0.0

## 启用 client-config, 目录里的文件名对应 client.crt 的 Common Name
client-config-dir /etc/openvpn/ccd

# /etc/openvpn/ccd/client-b
## 告诉 OpenVPN Server, 172.29.0.0/16 的下一跳应该是 client-b
iroute 172.29.0.0 255.255.0.0
内网与内网互访

在前两节所给的配置基础上,只需要再加一点配置,就能实现 OpenVPN 服务端所在局域网与客户端所在局域网的互访。配置内容是,在各自局域网的默认网关上添加路由,将对方局域网网段的下一跳设为 OpenVPN 服务端 / 客户端所在机器,同时用 iptables 配置相应的 SNAT 规则。

例如:

  1. Cluster A 的路由表里添加 172.31.0.0/16, 下一跳为 172.30.0.16 (cluster-a-relay).
  2. Cluster B 路由表里添加 172.30.0.0/16, 下一跳为 172.31.1.2 (cluster-b-relay).
延伸

​ 本文的配置适合大部分场景,因为公司没有公网IP,所以配置略繁琐,如果公司有公网Ip,那就省去了云服务器,直接将服务端部署在服务器上,配置转发路由即可,速度提升的同时,配置也会比较简单

​ 还有一种是ipspec的V服务,配置也很简单,重点是windows本身支持,不需要下载客户端,连接比较方便,这种的适合我刚才说的服务端部署在公司内网,且有公网Ip,安装方式参考

注意

server.conf每次安装里面的证书名称是随机的,所以如果之前备份的记住不要直接覆盖,把需要的替换进去就行