章節
- 概述
- 部署openvpn服務端
- 部署openvpn客戶端
- 測試
- 總結
一、概述
在實際的IT環境中會有這樣的需求:想讓兩個異地網絡層面互通,能夠互相訪問。常見的場景有:
- 兩個分支機構網絡互通,如分支機構實時將傳數據給總部處理
- 辦公室網絡與IDC機房互通,如運維或技術人員要遠程管理IDC機房內的服務器,IDC內的服務器也要訪問辦公室內網的服務器
- 兩個IDC機房內網互通,如兩邊同步數據、互相訪問等
當然,這樣的需求你可以拉專線但太貴,我們用openvpn來做
下面的例子:使用openvpn搭建vpn服務器打通A和B兩個異地網絡,讓A局域網中的172.16.10.0/24段可以和B局域網中的172.16.20.0/24段可以網絡互通,就好像在一個局域網一樣.
環境說明:
角色 | ip |
OPENVPN服務器 | 192.168.0.124/24(模擬外網) 172.16.10.206/24(內網) 10.8.0.1 10.8.0.2 (vpn虛擬網卡地址) |
OPENVPN客戶端 | 192.16.0.200/24 172.16.20.201/24(內網) 10.8.0.6 10.8.0.5 (vpn虛擬網卡地址) |
A局域網主機 | 172.16.10.207/24 |
B局域網主機 | 172.16.20.201/24 |
二、部署openvpn服務端(192.168.0.124)
關閉selinux
# setenforce 0 setenforce: SELinux is disabled
開啟路由轉發
編輯 /etc/sysctl.conf 文件將 net.ipv4.ip_forward = 0 改為 net.ipv4.ip_forward = 1,然后執行
# sysctl -p
安裝openvpn
# curl http://mirrors.aliyun.com/repo/epel-6.repo -o /etc/yum.repos.d/epel-6.repo --silent # 添加阿里的EPEL源 # yum install openssl openvpn easy-rsa lzo -y
創建相關目錄及配置
# mkdir /var/log/openvpn # 放openvpn相關日志文件 # mkdir /etc/openvpn/easy-rsa # 放easy-rsa包提供的相關工具 # mkdir /etc/openvpn/ccd # openvpn客戶端的配置目錄,后面會用到 # mkdir /var/run/openvpn # 放openvpn的pid文件
將easy-ras包提供的工具復制到 /etc/openvpn/easy-rsa
# cp /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa/ -r
編輯 /etc/openvpn/easy-rsa/vars 文件,找到下面的變量修改成你指定的值,后面生成證書的時候會應用這些變量值
export KEY_COUNTRY="CN" # 國家 export KEY_PROVINCE="GD" # 省份 export KEY_CITY="GZ" # 城市 export KEY_ORG="MY_ORG" # 組織/公司 export KEY_EMAIL="vpn@qq.com" # 郵箱 export KEY_OU="vpn" # 單位 export KEY_NAME="openvpn" # 服務器名稱
然后執行
# source vars # 導入vars文件中的變量作為當前的環境變量
# ./clean-all # 清除keys目錄下的文件
生成CA
也就是證書頒發機構,用來頒發證書
# cd /etc/openvpn/easy-rsa
# ./build-ca
生成服務器證書
# ./build-key-server vpnserver # 起個名字叫vpnserver Generating a 2048 bit RSA private key ................................+++ .....+++ writing new private key to 'vpnserver.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [GD]: Locality Name (eg, city) [GZ]: Organization Name (eg, company) [MY_ORG]: Organizational Unit Name (eg, section) [vpn]: Common Name (eg, your name or your server's hostname) [vpnserver]: Name [vpn]: Email Address [vpn@qq.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CN' stateOrProvinceName :PRINTABLE:'GD' localityName :PRINTABLE:'GZ' organizationName :PRINTABLE:'MY_ORG' organizationalUnitName:PRINTABLE:'vpn' commonName :PRINTABLE:'vpnserver' name :PRINTABLE:'vpn' emailAddress :IA5STRING:'vpn@qq.com' Certificate is to be certified until Apr 29 06:26:49 2026 GMT (3650 days) Sign the certificate? [y/n]:y # 輸入y 1 out of 1 certificate requests certified, commit? [y/n]y # 輸入y Write out database with 1 new entries Data Base Updated
生成客戶端證書
# ./build-key vpnclient # 起個名字叫vpnclient,表示為vpnclient這個客戶端生成證書 Generating a 2048 bit RSA private key .......+++ ....................+++ writing new private key to 'vpnclient.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [GD]: Locality Name (eg, city) [GZ]: Organization Name (eg, company) [MY_ORG]: Organizational Unit Name (eg, section) [vpn]: Common Name (eg, your name or your server's hostname) [vpnclient]: Name [vpn]: Email Address [vpn@qq.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CN' stateOrProvinceName :PRINTABLE:'GD' localityName :PRINTABLE:'GZ' organizationName :PRINTABLE:'MY_ORG' organizationalUnitName:PRINTABLE:'vpn' commonName :PRINTABLE:'vpnclient' name :PRINTABLE:'vpn' emailAddress :IA5STRING:'vpn@qq.com' Certificate is to be certified until Apr 29 06:30:42 2026 GMT (3650 days) Sign the certificate? [y/n]:y # 輸入y 1 out of 1 certificate requests certified, commit? [y/n]y # 輸入y Write out database with 1 new entries Data Base Updated
創建Diffie Hellman密鑰文件
需要一點時間
# ./build-dh
配置openvpn
編輯/etc/openvpn/server.conf文件,內容如下
local 192.168.0.124 port 1999 proto tcp-server dev tun ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/vpnserver.crt key /etc/openvpn/easy-rsa/keys/vpnserver.key dh /etc/openvpn/easy-rsa/keys/dh2048.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt client-config-dir /etc/openvpn/ccd push "route 172.16.10.0 255.255.255.0" # 推送給客戶端的路由,告訴客戶端添加靜態路由,讓去172.16.10.10/24網段的都走vpn服務器,vpn服務器后端又幾個網段就寫幾個 route 172.16.20.0 255.255.255.0 # 啟動時給openvpn服務器添加路由,告訴服務器去172.16.20.0/24網段的都走虛擬機網卡(tun0),相當於靜態路由. keepalive 10 120 comp-lzo max-clients 100 user nobody group nobody client-to-client duplicate-cn persist-key persist-tun status /var/log/openvpn/openvpn-status.log log /var/log/openvpn/openvpn.log writepid /var/run/openvpn/server.pid verb 3 mute 20
啟動openvpn服務端
# service openvpn start # chkconfig --add openvpn # chkconfig --level 35 openvpn on
查看tun0接口和路由
# ifconfig tun0 tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) # route -n | grep tun0 10.8.0.2 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 # 主機路由 172.16.20.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0 # 靜態路由,去172.16.20.0段下一跳是10.8.0.2 10.8.0.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0 # 靜態路由,去10.8.0.2.0段下一跳是10.8.0.2
指定客戶端配置
指定vpnclient這個客戶端的配置,編輯 /etc/openvpn/ccd/vpnclient ,內容如下
ifconfig-push 10.8.0.6 10.8.0.5 # 配置客戶端的IP iroute 172.16.20.0 255.255.255.0 # 告訴服務端,我的網段是172.16.20.0/24
三、部署openvpn客戶端(192.168.0.200)
關閉selinux
# setenforce 0
setenforce: SELinux is disabled
開啟路由轉發
編輯 /etc/sysctl.conf 文件將 net.ipv4.ip_forward = 0 改為 net.ipv4.ip_forward = 1,然后執行
# sysctl -p
安裝openvpn
# curl http://mirrors.aliyun.com/repo/epel-6.repo -o /etc/yum.repos.d/epel-6.repo --silent # 添加阿里的EPEL源 # yum install openssl openvpn easy-rsa lzo -y
創建相關目錄及配置
# mkdir /etc/openvpn/keys # 放客戶端的相關證書 # mkdir /var/log/openvpn # 放日志的目錄
將openvpn服務器上 /etc/openvpn/easy-rsa/keys 下的 ca.crt、vpnclient.crt、vpnclient.key 這些證書文件拉下來放到 /etc/openvpn/keys
# ls /etc/openvpn/keys ca.crt vpnclient.crt vpnclient.key
配置openvpn客戶端
編輯客戶端的配置文件/etc/openvpn/client.conf,內容如下
client dev tun proto tcp-client remote 192.168.0.124 1999 resolv-retry infinite nobind persist-key persist-tun ca /etc/openvpn/keys/ca.crt cert /etc/openvpn/keys/vpnclient.crt key /etc/openvpn/keys/vpnclient.key remote-cert-tls server
auth-nocache user nobody group nobody status /var/log/openvpn/openvpn-status.log log /var/log/openvpn/openvpn.log comp-lzo verb 3 mute 20
啟動openvpn客戶端
# service openvpn start
# chkconfig --add openvpn # chkconfig --level 35 openvpn on
客戶端啟動后只有進程,因為它作為客戶端去連服務端,不需要提供端口
# ps aux | grep vpn nobody 4236 0.1 0.3 46916 3232 ? Ss 01:36 0:00 /usr/sbin/openvpn --daemon --writepid /var/run/openvpn/client.pid --cd /etc/openvpn --config client.conf --script-security 2
查看tun0接口和路由
# ifconfig tun0 tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:10.8.0.6 P-t-P:10.8.0.5 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) # route -n | grep tun0 10.8.0.5 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 # 主機路由 10.8.0.0 10.8.0.5 255.255.255.0 UG 0 0 0 tun0 # 靜態路由,去10.8.0.0/24網段下一跳10.8.0.5 172.16.10.0 10.8.0.5 255.255.255.0 UG 0 0 0 tun0 # 靜態路由,去172.16.10.0/24網段下一跳10.8.0.5
四、測試(172.16.10.207、172.16.20.201)
在A局域網主機172.16.10.207上添加路由
ip route add 172.16.20.0/24 via 172.16.10.206 // 如果是linux route add 172.16.20.0 mask 255.255.255.0 172.16.10.206 // 如果是windows
上面的路由表示A去B局域網172.16.20.0段的下一跳是172.16.10.206,也就是把包轉發給vpnserver
在B局域網主機172.16.20.201上添加路由
ip route add 172.16.10.0/24 via 172.16.20.200 // 如果是linux route add 172.16.10.0 mask 255.255.255.0 172.16.20.200 // 如果是windows
上面的路由表示B去A局域網172.16.10.0端的下一跳是172.16.20.200,也就是把包轉發給vpnclient
最后,在A局域網主機 172.16.10.207 上ping 172.16.20.201
# ping 172.16.20.201 PING 172.16.20.201 (172.16.20.201) 56(84) bytes of data. 64 bytes from 172.16.20.201: icmp_seq=1 ttl=62 time=1.44 ms 64 bytes from 172.16.20.201: icmp_seq=2 ttl=62 time=0.752 ms 64 bytes from 172.16.20.201: icmp_seq=3 ttl=62 time=0.674 ms 64 bytes from 172.16.20.201: icmp_seq=4 ttl=62 time=0.785 ms ^C --- 172.16.20.201 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3023ms rtt min/avg/max/mdev = 0.674/0.913/1.441/0.307 ms
在B局域網主機 172.16.20.201上ping 172.16.10.207
# ping 172.16.10.207 PING 172.16.10.207 (172.16.10.207) 56(84) bytes of data. 64 bytes from 172.16.10.207: icmp_seq=1 ttl=62 time=5.72 ms 64 bytes from 172.16.10.207: icmp_seq=2 ttl=62 time=0.674 ms ^C --- 172.16.10.207 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1400ms rtt min/avg/max/mdev = 0.674/3.200/5.727/2.527 ms
兩邊可以ping通,表示OK
可以改進的地方
如果A和B局域網內很有多主機,那么每台機都要加很多次路由,比較麻煩,在實際的環境中可以在內網的路由器上做,這樣就不需要在主機上配,比較省事.
五、總結
vpn的目的和作用就是從網絡層面打通兩個或以上異地網絡,就好像在同一個局域網
vpnserver和vpnclient做好之后可以看成路由
如果要用vpn互相傳數據的話,帶寬盡可能大,有必要的話可以做端口綁定,高可用