VPN的主要作用是在局域网外部时也可以访问局域网的资源,比如学校有许多资源只能校内访问,而我们在校外还想访问学校资源,就需要通过入校VPN来实现,但是学校公用VPN用的人一多速度就会变得非常慢,不如利用自己校内固定IP的电脑自建一个VPN来的方便。
由于众所周知的原因,几种简单的VPN协议比如L2TP/IPsec和PPTP协议在大陆地区已经被干扰的基本无法正常使用了。因此也就SSL VPN还可以使用。SSL VPN有非常多种,但很多都是商业软件,不开源也不适合个人搭建。OpenVPN是一款开源的SSL VPN,可以很容易找到搭建的方法,非常符合我们的要求。
4月8日追记 我现在发现了一个更好用的开源SSL VPN——SoftEther,支持多种VPN协议包括OpenVPN,可以用它来代替OpenVPN服务器,具体搭建方法可参考本博客另一篇文章『Linux下SoftEther服务器搭建』
0x01 服务端配置
1. 准备工作
我们使用的是操作系统是最小安装模式的CentOS 7,进去后首先编辑/etc/selinux/config
关闭SELinux,因为SELinux总会引起一些奇奇怪怪的问题而且也没必要开启。然后因为学校本身有防火墙,就没必要在操作系统中再设置防火墙了,可以把firewalld
关闭掉
systemctl disable firewalld systemctl stop firewalld
2. 安装OpenVPN
yum -y install epel-release yum update yum -y install openvpn easy-rsa
3. 创建证书
下面是easy-rsa版本3以上创建证书的步骤
cd /usr/share/easy-rsa/3/ ./easyrsa init-pki ./easyrsa build-ca nopass ./easyrsa build-server-full <server-name> nopass ./easyrsa build-client-full <client-name> nopass
这里加上nopass
表示不用密码加密证书,因为就自己用,这样方便点。<server-name>
和<client-name>
分别是server和client的证书名,其中client证书可以创建多个,因为默认配置下一个证书只能同时有一个连接,所以一般是一个设备一个证书。
4. 准备OpenVPN配置文件
把上一步中创建好的证书等文件复制到/etc/openvpn/server/
目录下,并创建dh2048.pem
和ta.key
cd /usr/share/easy-rsa/3/pki cp ca.crt issued/<server-name>.crt private/<server-name>.key /etc/openvpn/server/ cd /etc/openvpn/server openssl dhparam -out dh2048.pem 2048 openvpn --genkey --secret ta.key
之后需要一个OpenVPN的配置文件<server-name>.conf
放在/etc/openvpn/server/
中,可以在样本配置文件/usr/share/doc/openvpn/sample/sample-config-files/server.conf
的基础上进行编辑
# 默认绑定在所有网络接口上,如需绑定在特定接口取消该行注释 ;local a.b.c.d # 监听端口 port 1194 # 运行模式,tun为L3层点到点链路,只能负载IP包,tap为 # L2层链路,负载以太网数据包,一般情况下tun即可 dev tun # 使用TCP或者UDP协议,可在其后加6监听IPv6端口 # 建议使用UDP协议,受干扰较小 ;proto tcp ;proto udp6 proto udp # 数据加密算法 cipher AES-256-CBC # 证书文件位置,和之前创建的证书名保持一致 ca ca.crt cert <server-name>.crt key <server-name>.key # OpenVPN分配的网段 server 10.8.0.0 255.255.255.0 # 如果需要分配IPv6网段取消下行注释,NAT的情况下使用 # 唯一本地地址(ULA)即fc00::/7下的地址段 ;server-ipv6 2001:db8:0:123::/64 # 保证同一个客户端(证书)每次连接时分配相同的IP地址 # 当需要客户端之间相互连接时非常有用 # 如果有多个OpenVPN服务器同时运行使用不同的文件名 ifconfig-pool-persist ipp.txt # 向客户端添加路由,使得客户端访问这些地址时通过OpenVPN进 # 行访问。一般设置目标局域网的网段。注意所有的push都可以 # 在客户端配置文件中设置,设置在服务端主要是因为方便 ;push "route 192.168.10.0 255.255.255.0" ;push "route 192.168.20.0 255.255.255.0" # 取消第一行注释后客户端所有的IPv4流量都会经过OpenVPN # 取消第二行注释后客户端所有的IPv4及IPv6流量都会经过OpenVPN # 适合想通过OpenVPN访问公网的情况,如果该项启用就不需要上一 # 项中向客户端添加额外的路由了 ;push "redirect-gateway def1 bypass-dhcp" ;push "redirect-gateway ipv6 def1 bypass-dhcp" # 如果客户端在连接OpenVPN之前使用的是本地局域网的DNS服务器, # 连接OpenVPN后由于路由改变可能会无法连接到之前的DNS服务器 # 因此需要修改客户端的DNS服务器地址,对于Windows等系统使用 # 以下的命令可以在连上OpenVPN时自动修改其DNS设置 ;push "dhcp-option DNS 208.67.222.222" ;push "dhcp-option DNS 208.67.220.220" # 保持连接参数,第一个参数为每隔几秒ping一次,第二个参数是多 # 少秒收不到包就认为是链路断开重新连接 keepalive 10 120 # 如果需要客户端之间能够相互访问,则打开该选项 ;client-to-client # 开启此选项后,同一个客户端证书可以同时建立多个连接 ;duplicate-cn # OpenVPN的状态日志,多个OpenVPN服务器使用分别的文件名 status openvpn-status.log # 以下内容一般不需要更改 # 可在样本文件中查看他们的详细说明 dh dh2048.pem tls-auth ta.key 0 persist-key persist-tun verb 3 explicit-exit-notify 1
5. 开启IP转发及NAT
使用以下命令开启IPv4以及IPv6转发,并使之生效
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf sysctl -p echo "IPV6FORWARDING=yes" >> /etc/sysconfig/network systemctl restart network
由于我们的服务器并不是路由器,因此即使对于IPv6也需要进行NAT才能使数据包正确地路由。利用iptables工具配置NAT,为了重启后也能生效可以把命令写在/etc/rc.local
中
iptables --table nat --append POSTROUTING --out-interface ens192 --jump MASQUERADE ip6tables --table nat --append POSTROUTING --out-interface ens192 --jump MASQUERADE
6. 启动OpenVPN服务
最后就可以启动OpenVPN了,可使用第二条命令使OpenVPN服务在重启后自动启动。
systemctl start openvpn-server@<server-name> systemctl enable openvpn-server@<server-name>
0x02 客户端配置
1. Windows系统
可以在OpenVPN的官网上下载到它的社区版本,安装后将之前在服务器上生成的ca.crt
、ta.key
、<client-name>.key
、<client-name>.crt
等文件复制到C:\Users\<your-user-name>\OpenVPN\config\
目录下,目录不存在的话创建一个即可。然后还需要一个在该目录下放一个后缀名为.ovpn的配置文件,可以在样本配置文件/usr/share/doc/openvpn/sample/sample-config-files/client.conf
的基础上进行编辑
# 使用TCP或者UDP协议,与服务端保持一致 ;proto tcp proto udp # 运行模式,和服务端保持一致 dev tun # 服务端的地址及端口,可以有多个服务端地址 remote my-server-1 1194 ;remote my-server-2 1194 # 当有多个服务端时,是否随机选择一个连接 # 默认是按照顺序连接 ;remote-random # 数据加密算法 cipher AES-256-CBC # 证书文件位置,和创建的证书名保持一致 ca ca.crt cert <client-name>.crt key <client-name>.key # 验证服务端证书,防止中间人攻击 remote-cert-tls server # 以下内容一般不需要更改 # 可在样本文件中查看他们的详细说明 client resolv-retry infinite nobind persist-key persist-tun tls-auth ta.key 1 verb 3
之后打开OpenVPN,双击屏幕右下角的OpenVPN图标或者右键选择Connect即可进行连接。
2. Android系统
Android上有两款OpenVPN客户端可以使用,一个是官方客户端OpenVPN Connect,还有一个开源的客户端OpenVPN for Android,都可以从Google Play上获取到。
这里我们只介绍官方客户端OpenVPN Connect的使用方法,与之前Windows下唯一的不同是,需要把证书等内容加入到.ovpn配置文件中变成一个文件然后导入OpenVPN Connect,因此配置文件需要做如下修改(可参考官方说明)
# 先把这几行注释掉 ;ca ca.crt ;cert <client-name>.crt ;key <client-name>.key ;tls-auth ta.key 1 # 然后加入下面的内容 # 下方省略号处贴入ca.crt文件内容 <ca> ...... </ca> # 下方省略号处贴入<client-name>.crt文件内容 <cert> ...... </cert> # 下方省略号处贴入<client-name>.key文件内容 <key> ...... </key> key-direction 1 # 下方省略号处贴入ta.key文件内容 <tls-auth> ...... </tls-auth>
之后将.ovpn文件复制到手机上,打开OpenVPN Connect选择OVPN Profile进行导入即可。
3. iOS系统
iOS系统可以在App Store里获取到官方客户端OpenVPN Connect,同样需要Android系统那样合为一的.ovpn配置文件。但是由于iOS系统的安全限制,导入.ovpn文件相比Android有一些不方便。
其中一个方法是用系统自带的应用“邮件”登录邮箱,然后将.ovpn文件作为附件向该邮箱发送一封邮件,之后在“邮件”应用中打开该.ovpn文件即可导入到OpenVPN Connect。
4. Linux系统
这里以CentOS 7为例,其他发行版类似。首先安装OpenVPN
yum -y install epel-release yum update yum -y install openvpn easy-rsa
之后将之前在服务器上生成的ca.crt
、ta.key
、<client-name>.key
、<client-name>.crt
等文件复制到/etc/openvpn/client/
目录下。目录下还需要一个<client-name>.conf
配置文件,可参考前文中Windows系统的配置文件,内容是一样的。最后通过命令systemctl start openvpn-client@<client-name>
就可以开启VPN了,关闭的话只需要输入命令systemctl stop openvpn-client@<client-name>
即可。
0x03 遇到过的问题
1. Windows虚拟机
目前在使用过程中发现,VMWare ESXi上的Windows虚拟机使用包含push "redirect-gateway def1 bypass-dhcp"
配置的服务器时,在连接上OpenVPN后会出现一些网络连接问题:
一个问题是连上OpenVPN后连不上Internet,通过以下步骤后可解决问题:1. 连接OpenVPN; 2. 打开网络共享; 3. 断开OpenVPN; 4. 自动诊断修复以太网卡(诊断的原因是此网卡未启用DHCP); 5. 连接OpenVPN; 6. 关闭网络共享。
上面的这个问题在Windows某次更新后消失了,但是出现了另一个问题,连上OpenVPN后无法通过原来的公网IP访问该Windows虚拟机,通过以下步骤后问题解决:1. 连接OpenVPN; 2. 打开网络共享; 3. 关闭网络共享。
2. Linux
OpenVPN服务端加上IPv6后发现原本正常的Linux客户端连接不上了,报如下错误
Mar 17 23:29:11 ovpn-client[23276]: /sbin/ip -6 addr add 2001:db8:0:123::1007/64 dev tun0 Mar 17 23:29:11 ovpn-client[23276]: Linux ip -6 addr add failed: external program exited with error status: 2 Mar 17 23:29:11 ovpn-client[23276]: Exiting due to fatal error
结果发现是由于sysctl
中net.ipv6.conf.all.disable_ipv6 = 1
导致IPv6配置被禁止,可通过cat /proc/sys/net/ipv6/conf/all/disable_ipv6
命令查看结果是否为1,如果是的话通过以下命令解决该问题
echo "net.ipv6.conf.all.disable_ipv6 = 0" >> /etc/sysctl.conf sysctl -p
你好,按照你的配置我只能连接一台内网的服务器(就是这台server),内网其它的服务器访问不了,请问如何解决,谢谢。
服务器端配置文件按需设置路由…配置文件每项都写了注释,你得照着按需改改啊
请问目前配置完内网可以连接了,但是如何通过内网穿透开放到外网?目前路由器无法设置,使用nps可以把其他应用开放出去,但是把openvpn的内网地址和端口开放出去却不行?请问该如何解决呢?
内网穿透的话OpenVPN应该不用特别设置吧,具体我也没有搞过。可以换成TCP协议看可不可以,或者换个内网穿透软件试一试?
因为目前路由器无法设置,所以直接用外网IP是不行的,然后目前是用的TCP协议,连接不上,其他的应用都可以。请问你设置的时候是用校内固定IP作为服务器IP还是?客户端设置的IP应该是外网的IP把?
我这里只有一个IP就是公网IP,不存在这些问题。而且你如果服务器配置文件不设置local那一行的话,OpenVPN是会绑定到所有IP上的。
恩,是的,不设置local也是不行,毕竟是在内网。你们有外网IP就比较方便。。
你好,按照这样配置的话可以多人同时使用vpn吗,可以的话能共用同一份客户端配置文件?
可以的