1. 程式人生 > >Ngrok+OpenVPN實現任意接入內網

Ngrok+OpenVPN實現任意接入內網

前言

目前來說,我們所在的內網(區域網)有很多,像公司的區域網,工廠的區域網,更為常見的校園網,很多資源的訪問需要在內網才可以。但是當我們在校外,出差等,往往訪問那些資源會很不方便,這時候經常會想到VPN技術。但是像學生是一般不會開放這種許可權或資源,需要自己搭建,前提是有一臺位於校園網邊界的伺服器,這個條件更難獲取,所以這裡我們採用Ngrok+OpenVPN的方式,藉助任意一臺內網的電腦,實現外網通過VPN接入內網,進而可以使用內網的各種資源。

實現原理圖

這裡寫圖片描述

Ngrok

  1. ngrok簡介
    ngrok 是一個反向代理,通過在公共的端點和本地執行的 Web 伺服器之間建立一個安全的通道。ngrok 可捕獲和分析所有通道上的流量,便於後期分析和重放。
  2. ngrok的搭建
  3. 首先準備一臺公網伺服器(可以從騰訊雲或阿里雲ECS,10元/月),主機安裝GO編譯環境
  4. 下載ngrok原始碼,修改部分引數
cd /usr/local/
git clone https://github.com/inconshreveable/ngrok.git
export GOPATH=/usr/local/ngrok/
/*此處為你的域名,直接使用IP一般會失敗,該域名後面會與證書繫結在一起,一定要確認正確,否則需要重新編譯*/
export NGROK_DOMAIN="zh-xxx.top" 
cd ngrok

生成證書

openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -out rootCA.pem openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days
5000

將生成的證書複製到指定的位置(當然在原始碼中也可以修改證書的位置,直接使用預設的比較方便)

cp rootCA.pem assets/client/tls/ngrokroot.crt
cp server.crt assets/server/tls/snakeoil.crt
cp server.key assets/server/tls/snakeoil.key

國內的伺服器需要修改下原始碼中的一個地址,國外的伺服器可以跳過這部分

vim /usr/local/ngrok/src/ngrok/log/logger.go
log "github.com/keepeye/log4go"

編譯服務端,amd64位64位電腦,根據伺服器CPU的型別正確填寫

cd /usr/local/go/src
GOOS=linux GOARCH=amd64 ./make.bash
cd /usr/local/ngrok/
GOOS=linux GOARCH=amd64 make release-server release-client

下面不再使用原來的客戶端,原來的客戶端經過一段時間的觀察,發現確實存在記憶體洩漏的問題,所以這裡推薦使用python編寫的客戶端(linux系統一般自帶python,windows系統則需要安裝下python,自行百度)

python原始碼的下載地址:
https://github.com/hauntek/python-ngrok

5.進入伺服器的目錄下執行ngrok的服務端,然後啟動客戶端即可。

cd /usr/local/ngrok/bin
/*這裡我們使用ngrok穿透內網,建立tcp連線,使用1194埠,這是OpenVPN預設的監聽埠*/
./ngrokd -domain="編譯時填寫的域名,一模一樣的域名" -proto=tcp 1194

由於服務端無法進入後臺模式,這裡可以使用screen使ngrokd執行在“後臺”,自行百度screen的用法

OpenVPN及搭建方式

  1. openvpn的簡介

OpenVPN 是一個基於 OpenSSL 庫的應用層 VPN 實現。和傳統 VPN 相比,它的優點是簡單易用。[1]
OpenVPN允許參與建立VPN的單點使用共享金鑰,電子證書,或者使用者名稱/密碼來進行身份驗證。它大量使用了OpenSSL加密庫中的SSLv3/TLSv1
協議函式庫。OpenVPN能在Solaris、Linux、OpenBSD、FreeBSD、NetBSD、Mac OS X與Windows
2000/XP/Vista上執行,幷包含了許多安全性的功能。它並不是一個基於Web的VPN軟體,也不與IPsec及其他VPN軟體包相容。[1]
OpenVPN2.0後引入了使用者名稱/口令組合的身份驗證方式,它可以省略客戶端證書,但是仍有一份伺服器證書需要被用作加密。
OpenVPN所有的通訊都基於一個單一的IP埠,
預設且推薦使用UDP協議通訊,同時TCP也被支援。OpenVPN連線能通過大多數的代理伺服器,並且能夠在NAT的環境中很好地工作。服務端具有向客
戶端“推送”某些網路配置資訊的功能,這些資訊包括:IP地址、路由設定等。OpenVPN提供了兩種虛擬網路介面:通用Tun/Tap驅動,通過它們,
可以建立三層IP隧道,或者虛擬二層乙太網,後者可以傳送任何型別的二層乙太網絡資料。傳送的資料可通過LZO演算法壓縮。在選擇協議時候,需要注意2個加密隧道之間的網路狀況,如有高延遲或者丟包較多的情況下,請選擇TCP協議作為底層協議,UDP協議由於存在無連線和重傳機制,導致要隧道上層的協議進行重傳,效率非常低下。

2.如何搭建OpenVPN

#安裝openvpn,easy-rsa用於生成證書使用,dnsmasq為域名相關
sudo apt-get -y install openvpn easy-rsa dnsmasq
#按如下操作,沒有的需要新建目錄,並把easy-rsa原安裝目錄複製一份到新建的目錄中
sudo cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa

編輯證書和金鑰的相關資訊

sudo vi /etc/openvpn/easy-rsa/vars
#找到下面的部分進行替換
export KEY_COUNTRY="CN"
export KEY_PROVINCE="SD"
export KEY_CITY="Liaoning"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="[email protected]"
export KEY_OU="MyOrganizationalUnit"

開始生成證書操作,首先通過su更新許可權為root使用者

#更新證書檔案
source vars
./clean-all

如果出現錯誤資訊,則開啟 vi clean-all開啟shell指令碼,手動執行,指令碼內容如下:

#!/bin/sh

# Initialize the $KEY_DIR directory.
# Note that this script does a
# rm -rf on $KEY_DIR so be careful!

if [ "$KEY_DIR" ]; then
    rm -rf "$KEY_DIR"
    mkdir "$KEY_DIR" && \
        chmod go-rwx "$KEY_DIR" && \
        touch "$KEY_DIR/index.txt" && \
        echo 01 >"$KEY_DIR/serial"
else
    echo 'Please source the vars script first (i.e. "source ./vars")'
    echo 'Make sure you have edited it to reflect your configuration.'
fi

主要是新建index.txt檔案,以及將01 寫入serial檔案這兩步:

 touch "$KEY_DIR/index.txt" 
 echo 01 >"$KEY_DIR/serial"

目錄建立完成開始生成證書:

cd /etc/openvpn/easy-rsa
#下面的操作請單步執行
#生成證書和私鑰
./build-ca
#生成伺服器的證書和私鑰
./build-key-server server
#生成Diffie-Hellman,用於不安全的通訊通道里安全的交換金鑰
./build-dh
#生成客戶端的證書和私鑰
./build-key

到目前為止,生成的所有檔案都在/etc/openvpn/easy-rsa/keys目錄下:

  • ca.crt – 證書頒發機構(CA)的證書
  • ca.key – CA的私鑰
  • server.crt – OpenVPN伺服器的證書
  • server.key – OpenVPN伺服器的私鑰
  • dh2048.pem – Diffie-Hellman引數檔案
  • client1.key –客戶端的私鑰
  • client1.crt –客戶端的證書
    -
    現在將生成的以上證書拷貝到openvpn目錄中,這是openvpn的預設證書訪問位置
#切換到keys目錄下
cp  ca.crt server.crt server.key dh2048.pem /etc/openvpn

到目前為止,我們已經生成了相關的證書和金鑰,證書的操作已經完成了。下一步需要設定openvpn伺服器

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz   /etc/openvpn/
#切換到 /etc/openvpn/目錄下
cd /etc/openvpn/
gunzip -d server.conf.gz
vi server.conf

在server.conf中需要修改幾處內容

1.首先定位到dh dh1024.pem,修改為dh dh2048.pem
2.#TCP or UDP server?
    proto tcp
    ;proto udp
    這是使用tcp方式,因為我們需要配合ngrok內網穿透服務
3.  dev tap
    ;dev tun
    這裡採用tap方式通訊,後面會用一篇文章來單獨解釋原因
4.  push "route 192.168.0.0 255.255.255.0"
    push "route 192.168.2.0 255.255.255.0"
    push "route 0.0.0.0  0.0.0.0"
    增加後面這一條,實現對openvpn伺服器後面的所有網段的轉發
5.  push "redirect-gateway def1 bypass-dhcp"
    取消這一行的註釋#,由openvpn伺服器做dhcp解析
6.  push "dhcp-option DNS 202.118.66.6"
    push "dhcp-option DNS 8.8.8.8"
    設定DNS伺服器地址,一般取公用的即可,其中一個取區域網內的解析地址
7.  user nobody
    group nogroup
    取消上面的兩行的註釋,增強伺服器安全性
8.  開啟點對點通訊
    client-to-client
完成以上修改儲存檔案
輸入openvpn server.conf,檢查配置檔案有無錯誤

現在可以啟動openvpn服務:

 systemctl start openvpn
 或者 
 service openvpn start

下一步需要設定路由:

vi /etc/sysctl.conf
#net.ipv4.ip_forward=1取消這行的註釋
儲存檔案,
/sbin/sysctl -p  使配置生效

配置OpenVPN客戶端檔案:

1.  使用tap的通訊方式
    dev tap
    ;dev tun
2.  建立tcp連線方式
    proto tcp
    ;proto udp
3. 配置連線伺服器的地址或域名
    remote my-server-1(替換為地址) 1194
4.  保證證書的位置正確
    ca ca.crt
    cert client.crt
    key client.key

儲存檔案並退出

最後啟動OpenVPN的客戶端建立連線即可。