使用OpenVPN连通管理多个阿里云VPC网络
这篇文章比较长,将从需求、思路、原理、架构、实施步骤、细节分析、高可用等几个方面来讲述OpenVPN的使用,如果看到很熟悉的内容或者不感兴趣的部分,请您跳过。
需求
公司网络环境更换,导致原来连接阿里云的VPN现在只能建立一个连接,网管解决不了,所以只好换别的VPN解决方案。阿里云自身有提供相关产品,既支持VPN网关连接,也支持单点SSL连接,还有高可用支持,唯一的缺点就是小贵,对于我这种平常简单管理使用有点不值。因为和谐上网的需要,之前也了解过有哪些免费VPN服务器可用,这次首先就想到了OpenVPN。
这里有三个环境:公司内部网络、阿里云测试环境、阿里云生产环境。
测试环境和生产环境都基于阿里云VPC,都是私网,其中的机器都不能互相访问。
测试和生产环境可以用来部署OpenVPN的机器都是Windows操作系统。
需要在公司多人同时连接测试环境和生产环境,并能够访问其中的所有机器。
测试环境和生产环境目前不需要互通,以后可能有这方面的需求。
测试环境和生产环境不需要主动访问公司网络,以后也不会有这方面的需求。
思路
在生产环境部署OpenVPN Server,在测试环境和公司内部部署OpenVPN Client。
利用OpenVPN的client to client能力,使VPN节点之间互相可以访问,并能够路由请求到节点所在私网的其它机器,从而实现物理隔离的私网之间的互通;然后再使用防火墙(阿里云安全组)精细控制不同私网之间的访问权限,比如以后测试环境和生产环境的互通控制需求。
原理
因为使用OpenVPN的桥接模式没有成功,而且路由模式访问控制更加灵活,所以这里介绍的是OpenVPN的路由模式。
先简单看一张图,因为网上介绍的大部分都是在Linux上安装配置的,Windows上的Tun/Tap驱动如何实现的不是很清楚,但是应用到OpenVPN原理上应该差不多。其中用户态和核心态可以这样理解:用户态就是应用程序,核心态就是操作系统。
OpenVPN是IP层的VPN,节点安装后会在本机创建一个虚拟网卡;OpenVPN Server可以将访问OpenVPN其它节点所在私网的路由推送到OpenVPN Client,这些路由的接口对应到当前机器的虚拟网卡;所有使用VPN网络的应用将发送数据到这些虚拟网卡;OpenVPN会读取虚拟网卡的数据,封装后通过真实网卡发送到其它节点,以及从真实网卡接收从其它节点发送的数据,解析后发到虚拟网卡,然后数据再被使用VPN网络通信的具体应用获取到。
部署架构
在开始安装之前,先来看下整体的部署架构。
三个物理网络的网段分别为(注意这些网络不能有重复的,否则会有冲突无法正常连接):
公司内网:192.168.0.0/24
阿里云测试环境:172.31.200.0/24
阿里云生产环境:172.31.201.0/24
VPN网络的网段为:10.250.250.0/24
黑色的实线是实际的网络连接,三个环境分属不同的私网,他们和互联网都通过网关相连。
蓝色的虚线是VPN网络,VPN网络由OpenVPN的Server和Client节点组成,Server同时充当VPN网络的网关。
参与到VPN网络的三台机器都是私网内部的机器,非私网的网关服务器,需要给OpenVPN Server所在的机器绑定一个阿里云的弹性公网IP,因为客户端要跨越互联网来连接它。
如果VPN节点部署在网关服务器,很多路由就不用单独配置了,不过阿里云上无法实现,部署过程中会提到这些路由。
部署步骤
1、安装OpenVPN
国家将OpenVPN的网站和谐了,但是我们这里不是用于非法目的,所以需要自己想办法搞一个安装包,我这里版本是:2.4.6。
安装服务器端和客户端的基本上是一样的,需要注意服务器端要用来生成证书和密钥,所以安装服务器的时候把EasyRSA这个选项勾上。
2、创建证书和密钥
OpenVPN节点之间的通信需要认证和加密。 通过Windows自带的命令行管理工具进入easy-rsa目录,默认是在C:\Program Files\OpenVPN\easy-rsa 然后执行如下命令初始化环境:
init-config vars clean-all
然后生成CA根证书:build-ca,注意Common Name不要和后边其它密钥的重复。
然后创建迪菲·赫尔曼密钥:build-dh,这个是用在协商VPN数据加密密钥时用到的。
然后创建ta证书:openvpn --genkey --secret keys/ta.key,这个是用来防御DoS、UDP淹没等恶意攻击。
然后生成服务器端证书:build-key-server server,注意Common Name不能重复,这里还需要设置一个证书密码,随便取就行。
然后生成两个客户端 证书:build-key testclient、build-key comclient,两个证书分别为测试环境和公司环境,Common Name不能重复,证书密码随便取。
这些证书或者密钥文件会生成到easy-rsa/keys目录下。
如果关闭了这个窗口,下次再生成证书的时候需要先执行下vars命令,加载变量到当前运行环境。
建议将ca.key文件放到一个离线的机器上,需要生成客户端证书的时候再复制过来,防止文件被窃取导致安全问题。
关于创建证书这块网上教程比较多,我这里没有截图,不明白的可以参考这个:https://www.cnblogs.com/airoot/p/7201227.html
3、配置并启动Server节点
server的配置文件需要放到安装目录的cnofigs目录下,包括:ca.crt、dh2048.pem、server.crt、server.key、ta.key、server.ovpn。
除了server.ovpn,其它文件都从easy-rsa/keys拷贝就可以了。
server.ovpn可以从 OpenVPN安装目录/sample-config 拷贝一个,然后根据需要进行修改,这里提供下这里的配置:
# OpenVPN监听地址,不配置默认所有本地地址 ;local a.b.c.d # 监听端口,默认1194 port 1194 #使用UDP协议,IPv4,效率比TCP更高 proto udp4 # 使用路由模式 dev tun # 虚拟网卡的名称,也可以注释掉 dev-node OVPN # CA证书和服务端密钥文件配置 ca ca.crt cert server.crt key server.key dh dh2048.pem # 使用subnet,每个OpenVPN节点分配一个VPN子网的IP地址 topology subnet # OpenVPN分配IP的网络号和子网掩码,这里支持254个节点 server 10.250.250.0 255.255.255.0 # VPN客户端分配的IP记录,客户端重启后可以继续使用 ifconfig-pool-persist ipp.txt # 需要把这些子网路由推送到VPN客户端,VPN客户端会自动判断是否本地网段,如果不是才会添加 # VPN客户端所在机器根据这些路由转发对私网的网络请求 push "route 172.31.200.0 255.255.255.0" push "route 172.31.201.0 255.255.255.0" # client-to-client将开放VPN客户端之间的互相访问 # client-config-dir ccd是指定客户端配置文件的目录,Windows在 OpenVPN安装目录/configs 下 # 这里因为要实现对测试环境子网的访问,所以要添加一个testclient配置文件,里边给出到VPN客户端testclient节点的路由 client-to-client client-config-dir ccd # 控制从系统核心到OpenVPN的路由,即在OpenVPN Server所在机器增加到VPN客户端testclient的路由 # 到172.31.200.0/24的请求将通过本机虚拟网卡发送,然后通过OpenVPN Server封装后发送到真实网络 route 172.31.200.0 255.255.255.0 keepalive 10 120 tls-auth ta.key 0 cipher AES-256-CBC persist-key persist-tun status openvpn-status.log verb 3 explicit-exit-notify 1
在ccd文件夹中新建名为testclient的文件,为testclient指定OpenVPN内部路由配置,也就是从OpenVPN Server到testclient节点的路由,文件内容:
iroute 172.31.200.0 255.255.255.0
现在就可以启动OpenVPN Server了。
启动OpenVPN GUI,在任务栏中右键点击Connect,连接成功后会有提示,并分配一个VPN的IP,这个IP应该是VPN网段的第一个IP,这里是10.250.250.1。
4、配置并启动阿里云测试环境Client节点
client的配置文件也是放到本机OpenVPN安装目录下configs中,包括:ca.crt、testclient.crt、testclient.key、ta.key、testclient.ovpn。
除了testclient.ovpn外,其它四个文件都是在OpenVPN Server生成的,拷贝过来就可以了。这里看下testclient.ovpn的配置:
# 声明节点为client client # tun模式 dev tun # 使用UDP通信 proto udp # OpenVPN Server服务器外网IP,请在阿里云给服务器绑定个弹性公网IP,然后写到这里 remote 123.x.x.x 1194 # 断网无限重试 resolv-retry infinite # 本地不使用固定端口 nobind persist-key persist-tun # 证书文件 ca ca.crt cert testclient.crt key testclient.key # server段证书 remote-cert-tls server tls-auth ta.key 1 cipher AES-256-CBC verb 3
启动OpenVPN GUI,在任务栏中右键点击Connect,连接成功后会有提示,并分配一个VPN的IP。
5、配置并启动公司Client节点
公司Client节点和阿里云测试环境Client节点是差不多的,区别就是证书文件不同,公司Client节点的使用comclient.crt、comclient.key,替换相关文件就可以了。
comclient.ovpn可以复制testclient.ovpn,然后修改其中的cert和key的名字。
启动OpenVPN GUI,在任务栏中右键点击Connect,连接成功后会有提示,并分配一个VPN的IP。
VPN节点之间现在可以相互访问和连接了,可以试试ping一下。但是对于各个节点子网的访问还要继续配置下。
6、开放子网机器给VPN网段
阿里云的ECS服务器都会归属于某个安全组,安全组可以设置数据按照端口和协议进出的规则。默认情况下,安全组的入方向是全部被拒绝的,如果要从VPN网段访问这些机器,需要增加一个入方向的规则。这个规则在测试环境和生产环境都需要添加。
7、添加VPN网段路由
这时候会发现从客户端还是访问不了Server节点所在子网的其它机器,这是因为虽然数据可以到达这些机器,但是响应的数据无法回复给客户端,因为这些机器通过路由找不到客户端;所以生产环境这里还要做两个配置:
(1)在阿里云生产环境网关路由表中增加对VPN网段的路由,将VPN网段路由到OpenVPN Server所在机器。
(2)在OpenVPN Server上启动路由服务,也就是Windows服务:Routing and Remote Access 如果没有这个服务,请首先安装Windows组件:路由和远程访问,安装后应该就有了,注意不要配置NAT。
现在应该可以从客户端节点访问到Server节点所在子网的其它机器了。
阿里云测试环境也要做相同的配置:添加到VPN网段的路由,启动OpenVPN所在服务器的路由服务,这里就不啰嗦了。
这两个配置完成以后,就可以从公司网络连接阿里云测试和生产环境的所有机器了。
但是不要高兴的太早,这时候访问测试环境和生产环境的互通还是不行的,为什么呢?还是路由的问题,OpenVPN Server所在子网的机器找不到去测试环境网段的路由;所以在阿里云生产环境VPC路由中还需要增加路由条目,和上边类似: 目标网段换成172.31.200.0/24,下一跳还是OpenVPN Server所在的服务器。
这样就可以实现测试环境和生产环境的互访了。
8、控制测试环境和生产环境的互访权限
测试环境和生产环境的互通是比较危险的,因为如果部署的时候搞错配置,到时候数据可能乱掉。但是有时候一些公共的查询服务没必要搞两份,比如天气服务只在生产环境搞一份就行了,测试环境要使用也访问这个。这个问题一般可以通过防火墙解决,在阿里云上有一个安全组的概念,可以用来干这件事。比如这样配置:
这里完全禁止了测试环境访问生产环境,上边的端口范围可以根据自己的需要调整。阿里云入方向其实默认是全部禁止的,需要自己开放端口和协议。可以自己试试看看效果。
到这里安装配置基本上就完成了,感觉还是很繁琐的,中间的事比较多,希望读者能够顺利完成。但是从另一个方面也说明这个方案实现网络访问控制很灵活,可以配置的东西比较多。
细节分析
如果你很想搞清楚在VPN网络中数据是怎么流转的,以及上边的这些配置到底是怎么发挥作用的,这里写了一个流程,希望能够帮助到你。
以公司某台电脑C1: 192.168.0.220使用远程桌面访问生产环境某台服务器S1: 172.31.201.110为例:
1、C1安装OpenVPN后本机会创建一个虚拟网卡,这时候虚拟网卡还没有连接;
2、将OpenVPN Client连接到Server节点后,会分配到一个VPN地址(比如10.250.250.4),以及创建到生产环境的路由信息,这些信息是Server节点push过来的;
3、C1现在要访问S1了,通过本机路由信息得知需要走10.250.250.4对应的虚拟网卡接口;
4、C1的远程桌面客户端发送S1的连接请求,请求访问操作系统网络调用,最终封装为一个IP报文,通过虚拟网卡发送;
5、C1的OpenVPN此时会读取到通过虚拟网卡发送的数据,然后在IP报文的外层再包裹IP头和UDP协议,指示要前往生产环境时的真实网络IP信息,然后提交到C1的真实网卡;
6、C1的真实网卡会将数据通过本地网关发到互联网,最终发到生产环境OpenVPN 所在服务器V1,V1的真实网卡会根据UDP协议关联到当前节点的OpenVPN程序进行数据接收;
7、V1的OpenVPN取出内层的IP报文,发现目标地址172.31.201.110为局域网内部,通过局域网网关获取目标服务器Mac地址,直接走真实网卡,然后就到达了S1;
8、S1收到建立远程桌面的请求后,要给对方回个消息,这时候要知道数据发向哪里,它会发一个ARP广播,寻找10.250.250.4的物理地址;
9、生产环境的局域网中没有10.250.250.4,但是生产环境的网关知道,对于10.250.250.4请发送到OpenVPN 所在服务器V1;
10、V1服务器启动了路由服务,也就是V1是个路由器,会继续发现到10.250.250.4需要走本地虚拟网卡10.250.250.1,并获取虚拟网卡的Mac地址;
11、然后数据到达V1,通过V1的虚拟网卡进行发送,V1上的OpenVPN获取到响应数据,将这些数据再次封装,通过真实网卡、网关和互联网发送到公司内部的C1服务器;
12、C1的真实网卡会根据UDP协议关联到当前节点的OpenVPN程序进行数据接收,OpenVPN取出内层的IP报文,根据本地路由查找发现是给虚拟网卡的,然后写数据到虚拟网卡;
13、然后C1上的远程桌面客户端会从虚拟网卡中读取到S1发送给自己的数据。
这样就完成了一次数据的交互,后续的数据交互都是按照这个流程去走,中间过程还是比较复杂的,而且我省略了很多底层机制,重点描述了OpenVPN对数据的处理过程。
高可用
OpenVPN官网上有一个负载均衡/故障转移的策略:
原文:https://openvpn.net/community-resources/implementing-a-load-balancing-failover-configuration/
方法是部署多个OpenVPN Server,然后客户端的配置文件可以配置多个Server地址,客户端连接的时候可以随机从这些Server中选择,然后进行连接,如果Server连接不上了,则尝试连接别的Server。这个方案中证书密钥那一套共用就可以了,但是VPN网络的网段要区分开,比如一个使用172.31.202.0/24、另一个就使用172.31.203.0/24。
从网上搜索到的都是这个方案,但是这个方案只能保证OpenVPN Server的高可用。
如果是两个互通的私网,OpenVPN Client不可用时也就不能互通了。一个解决方案是Client也部署多个,分别连接到不同的Server,这样就有多个VPN网络可用了。但是要保证所有Client端和Server端的私网路由都指向同一个VPN网络的节点服务器,因为不能同时设置同一网段的路由到多个不同的VPN网络节点服务器,这还是有点难度的。
这时可以写一个测试环境驻守程序监控与生产环境的通信状态,如果连不上了,则说明当前的连接可能出现问题了,此时可以调用修改路由条目的API,将到其它私网的路由线路切换到别的OpenVPN Client节点服务器,同时还要通知所有要访问本网络的其它私网都修改下路由条目,以使大家都在同一个VPN网段内。这个分布式协调比较困难,如果可用性要求不是很高,出问题时通知人来处理会简单很多。
在阿里云上还有变通的方案,OpenVPN不是部署多套,而是在检测到节点服务器异常时,通过阿里云API迁移部署到正常的服务器,还使用原来的服务器IP(弹性IP),以及OpenVPN配置,这样路由规则不需要改变。如果不是在阿里云上,使用vip+keepalived,再加一些触发机制是不是也能实现?如果使用桥接模式是不是很容易就能解决这个问题了呢?这些方案因为成本较高,我没有测试,有兴趣或者需要的可以试试。
后记
写这篇文章主要是为了总结使用OpenVPN的技术经验,很多知识也是边写边查,因为涉及到的网络知识特别多,很多也没有提及或者展开,能力确实有限,可能有些描述错误之处,欢迎给我反馈。
本篇同步发布到个人独立博客:https://blog.bossma.cn/server/openvpn-manage-multiple-vpc-network-with-windows-server-and-tun-style/
使用OpenVPN连通管理多个阿里云VPC网络的更多相关文章
- IDC机房与阿里云vpc网络建立高速通道
本操作以下图所示的场景为例,演示如何通过高速通道建立本地数据中心与VPC之间的私网通信. 前提条件 已提交工单获取接入点的地理位置. 步骤一: 申请物理专线并完成专线接入 登录高速通道管理控制台. 在 ...
- 阿里云vpc网络SNAT实现内网实例通外网
需求场景: 因费用和安全考虑,内网部分机器没有分配公网IP,没绑定弹性公网IP,没有购买NAT服务,但是内网机器需要访问外网部分资源,如发送邮件. 操作步骤如下: 1.查看外网上的转发功能的开启没开启 ...
- 五:用JAVA写一个阿里云VPC Open API调用程序
用JAVA写一个阿里云VPC Open API调用程序 摘要:用JAVA拼出来Open API的URL 引言 VPC提供了丰富的API接口,让网络工程是可以通过API调用的方式管理网络资源.用程序和软 ...
- 阿里云VPC绑定EIP实现SNAT
阿里云VPC需要了解的几个问题 什么是VPC 虚拟私有网络(Virtual Private Network),能够帮助用户基于阿里云构建出一个隔离的网络环境.用户可以完全掌控自己的虚拟网络,包括选择自 ...
- 多云混合云之多集群统一管理:基于阿里云ACK统一纳管多个不同Kubernetes集群
目前阿里云云原生产品家族已经支持多集群管理功能,允许使用阿里云容器服务Kubernetes(简称ACK)控制台或kubectl命令接入.统一纳管其他公有云.客户IDC自建K8s集群,集中管理部署K8s ...
- 阿里云异常网络连接-可疑WebShell通信行为的分析解决办法
2018年10月27日接到新客户网站服务器被上传了webshell脚本木马后门问题的求助,对此我们sine安全公司针对此阿里云提示的安全问题进行了详细分析,ECS服务器被阿里云提示异常网络连接-可疑W ...
- 最佳实践:阿里云VPC、ECS支持IPv6啦!
12月6日,阿里云宣布为企业提供全栈IPv6解决方案. 阿里云专有网络VPC.云服务器ECS,作为阿里云的核心产品,也于2018年11月底上线双栈VPC.双栈ECS,目前正在对外公测中. 那么如何在阿 ...
- 阿里云VPC网络内网实例通过SNAT连接外网
场景: 1.有多个ECS实例,其中A实例有公网IP,可以上外网 其它实例没有公网IP,不能上外网 2.所有实例在一个交换机,也就是一个网络(172.16.0.0/16) 实例 内网IP 外网IP A ...
- 阿里云RDs 网络白名单 专用网络 经典网络
云服务为了安全性总是有不同的安全规则,第一就是需要明白里面的网络类型 专有网络是您自己独有的云上私有网络.您可以完全掌控自己的专有网络,例如选择IP地址范围.配置路由表和网关等,您可以在自己定义的 ...
随机推荐
- Hql语句转化为sql语句中文乱码问题
刚刚学习Hql语句就出现这一的问题,百度半天终于解决了,总结一下解决的方案: 出现中文乱码最可能的原因是hibernate配置文件配置的问题 1.检查url路径是否指定字符集为UTF-8 <pr ...
- HTML5拖拽功能中 dataTransfer对象详解
有了HTML5,老板再也不用担心我们的上传了,再加上有拖拽上传是不是很酷.百度一下,有关HTML5拖拽上传的文章和实例不少,都缺不了一个至关重要的东东DataTransfer.但是详细介绍的不多,尤其 ...
- Python入门教程
http://www.cnblogs.com/vamei/archive/2012/09/13/2682778.html
- servlet中cookie和session操作
1.1 软件中的会话 一次会话: 打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器 登录场景: 打开浏览器 -> 浏览到登陆页面 -> 输入用户名和密码 -> 访问 ...
- springmvc/springboot处理前台字符串日期自动转换成后台date类型的三种办法
参考https://blog.csdn.net/eumenides_/article/details/79033505 补充一个:Formatter也可以实现.
- nodejs + redis/mysql 连接池问题
nodejs + redis/mysql 连接池问题 需不需要连接池 连接池的作用主要是较少每次临时建立连接所带来的开销.初步一看,nodejs运行单线程上,它不能同时使用多个连接,乍一看是不需要连接 ...
- Session和Cookie详解(1)
面试常问的有关session和cookie的问题: 1.session在分布式环境下怎么解决 2.集群下如何保证session踩中 3.cookie的大小 4.服务器怎么识别一个用户的 5.sessi ...
- java面试题之----jdbc中使用的设计模式(桥接模式)
1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...
- 工作笔记—hibernate之QueryCriteria
本人用的是sg-uap虚拟环境 //查询方法 //参数 RequestCondition 配合 controller 的 @QueryRequestParam注解可以将前台传入整个对象进行接收 //参 ...
- centos 克隆系统放到别的机器上后出现网卡启动不了的情况
1. Remove Network Manager from startup Services. #chkconfig NetworkManager off 2. Add Default Net ...