我的 GitHub 原文:手把手教你,搭建內網穿透服務
在很多場景下內網穿透都是我們常常遇到的需求,之前也用過花生殼、ngrok、FRP 等等一些工具,但是由於限速、收費、安全各方面因素只好放棄了。
目前所在實驗室主要從事深度學習和機器學習相關工作,有一臺高配 GPU 計算型服務器,大家使用 Jupyter Notebook 在網頁上進行編碼工作,但是只能在學院內網才能進行使用,在外面就無法使用讓人比較抓狂。如果購買阿里雲等深度學習服務,價格昂貴,只好決定通過內網穿透實現公網工作。
近期無意間看到 「傳送門:lanproxy」 這款開源工具,正好實驗室購置了一臺公網服務器,正好可以實現內網穿透,決定入坑折騰一番。對於有後臺開發基礎的同學還是挺簡單的,不過好記性不如爛筆頭,來吧,這裏手把手深入探索一番。
一、概述
1.1 什麼是內網穿透
好吧,先上一段百度百科的定義
內網穿透,即NAT穿透,網絡連接時術語,計算機是局域網內時,外網與內網的計算機節點需要連接通信,有時就會出現不支持內網穿透。
反正簡單來說,就是能通過公網訪問你的內網服務,把你的內網通過一臺公網服務器,穿透出去。
1.2 什麼是 lanproxy
lanproxy 是一個將局域網個人電腦、服務器代理到公網的內網穿透工具,目前僅支持 tcp 流量轉發,可支持任何 tcp 上層協議(訪問內網網站、本地支付接口調試、ssh 訪問、遠程桌面…)。目前市面上提供類似服務的有花生殼、TeamView、GoToMyCloud 等等,但要使用第三方的公網服務器就必須爲第三方付費,並且這些服務都有各種各樣的限制,此外,由於數據包會流經第三方,因此對數據安全也是一大隱患。https://lanproxy.io2c.com
1.3 原理
內網穿透的原理如下圖所示:
-
用戶訪問我們的服務器,這個服務器是有公網IP的,所以用戶可以無壓力訪問
-
服務器與本地電腦保持長鏈接,當有請求的時候,服務器將請求轉發到我們的本地電腦
-
本地電腦將響應回覆給服務器
-
服務器將響應回覆給用戶
要搭建內網穿透,我們得完成兩個任務
- 在公網能訪問的服務器上運行我們的內網穿透服務;
- 在本地電腦上面運行內網穿透客戶端。
當然,你可以自己根據原理實現一套,不過我們有現成的三方開源工具,可以幫我們實現這一套功能。這個就是我們今天的主角 lanproxy。
二、快速開始
這裏我將手把手帶你配置 lanproxy 穿透服務,這裏配置主要分成了 公網服務器配置 和 內網電腦配置 。
在內網電腦配置中分爲:Java 客戶端和 GO 客戶端
2.1 硬件與環境要求
這裏以我的環境爲例
- 一臺公網服務器(Centos 7.4,當然這不重要,反正都 docker 啦)
- docker(簡化更多的配置,這裏採用 docker 容器進行搭建)
- Nginx 環境
- 一臺內網電腦(Ubuntu 16.04)
- Java JDK 1.8
- Maven(包依賴管理工具)
- docker 啓動服務,tensorflow(jupyter notebook)
- 已備案的域名
- 此步驟也可省略,但端口太多通過 Nginx 配合域名進行轉發,使用更加方便。故這裏我也將會配置兩個公網域名
2.2 公網服務器配置(Docker 一鍵啓動)
基礎環境安裝
- 安裝 docker 服務,以 CentOS 7.4 爲例
1、安裝依賴包
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
2、設置穩定版倉庫
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
3、安裝
//安裝最新版本
$ sudo yum install docker-ce
//或者安裝指定版本
$ yum list docker-ce --showduplicates | sort -r
//顯示有以下版本
docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable
//指定一個版本進行安裝
$ sudo yum install docker-ce-<VERSION STRING>
4、啓動doker
$ sudo systemctl start docker
5、通過運行hello-world鏡像驗證安裝是否成功
$ sudo docker run hello-world
- 安裝 Nginx 服務,以 CentOS 7.4 爲例
1.添加Nginx到YUM源
$ sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
2.安裝Nginx
$ sudo yum install -y nginx
Nginx將完成安裝在你的CentOS 7 服務器中。
3.啓動Nginx
$ service nginx start
通過 Docker,啓動 lanproxy 服務
啓動 Docker 後運行一下代碼
docker run -d \
--name lanproxy-server \
-p 8090:8090 \
-p 4900:4900 \
-p 4993:4993 \
-p 9000-9100:9000-9100 \
biodwhu/lanproxy
輸入你的公網服務器 IP:8090,例如:http://120.92.10.120:8090/,即可看到如下的界面。好啦,到這裏 lanproxy 的基礎環境已經搭建成功,是不是很快,這就是 docker 的魅力。如果不用 docker 啓動,請參考 lanproxy 的官方文檔。
默認:account/password:admin/admin
Nginx 反向代理配置域名
在上一步,我們通過 docker 啓動了一個 lanproxy 環境,但是通過 IP 和端口號組合的方式並不優雅。這裏我將解析兩個域名通過 Nginx 進行端口轉發。
# 兩個域名都解析到你的公網上去
# 這個域名由於訪問 lanproxy 管理後臺
lanproxy.frankfeekr.cn => 120.92.10.120 | Nginx to => 127.0.0.1:8090
# 這個域名由於訪問你的內網電腦服務,9000 端口可自由的在 lanproxy 管理後臺進行配置
jupyter.frankfeekr.cn => 120.92.10.120 | Nginx to => 127.0.0.1:9000
好啦,上門就是對域名進行了一些簡單的解釋,現在開始 Nginx 的配置
-
進入
/etc/nginx/conf.d
Nginx 的配置目錄,在這裏創建配置文件 -
創建
lanproxy.frankfeekr.cn.conf
配置文件
server {
listen 80;
# 這裏使用自己的域名
server_name lanproxy.frankfeekr.cn;
charset utf-8;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
# 這裏根據你的 lanproxy 配置,改成 config.server.port的值
proxy_pass http://127.0.0.1:8090;
client_max_body_size 35m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- 創建
jupyter.frankfeekr.cn.conf
配置文件
server {
listen 80;
# 這裏使用自己的域名
server_name jupyter.frankfeekr.cn;
charset utf-8;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
# 這裏根據你的lanproxy配置,改成 外網接口 的值,在lanproxy後臺網頁上配置,後面配置
proxy_pass http://127.0.0.1:9000;
client_max_body_size 35m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- 重啓 Nginx 服務
$ service nginx restart
至此,你可以通過域名 http://lanproxy.frankfeekr.cn 進行訪問 lanproxy 網頁後臺配置
繼續配置 lanproxy 後臺服務
- 添加一個客戶端
- 添加配置
至此,服務端的配置就完成了。下面開始內網電腦的配置。
2.3 內網電腦配置(Java 客戶端)
這裏我的內網是一臺 Ubuntu 16.04 的服務器,以下我都將以此爲例
Java 1.8 安裝
- 下載 JDK1.8(lanproxy 支持 JDK1.7 以上環境)
$ wget https://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jdk-8u191-linux-x64.tar.gz
- 解壓安裝包,移動文件夾到 /user/lib 目錄
$ tar -zxvf jdk-8u191-linux-x64.tar.gz
$ mv jdk1.8.0_191 /usr/lib/jdk/jdk1.8.0_191
-
環境變量配置
這裏是將環境變量配置在 etc/profile,即爲所有用戶配置 JDK 環境。
$ vim + etc/profile
環境設置
#set java env
export JAVA_HOME=/usr/lib/jdk/jdk1.8.0_191
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
執行命令使修改立即生效
$ source /etc/profile
-
配置軟連接
軟連接相當於windows系統中的快捷鍵,部分軟件可能會從/usr/bin目錄下查找Java,因此添加該軟連接防止其他軟件查找不到的情況。
$ sudo update-alternatives --install /usr/bin/java java /usr/lib/jdk/jdk1.8.0_191/java 300
$ sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jdk/jdk1.8.0_191/bin/javac 300
- 測試安裝是否成功
# 在終端輸入,出現版本號則表示安裝成功
$ java -version
更詳細文檔:
maven 安裝
maven 是個項目管理工具,在編程領域應用廣泛。
- 官網 下載maven。
$ wget https://www-eu.apache.org/dist/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
- 解壓到 /opt/maven 目錄
創建 manve 目錄。
$ sudo mkdir /opt/maven
解壓到 /opt/maven 目錄下。
$ sudo tar zxvf apache-maven-3.6.0-bin.tar.gz -C /opt/maven
- 配置 maven 環境
$ vim + /etc/profile
在文件內容後面添加以下內容:
# set maven env
export M2_HOME=/opt/maven/apache-maven-3.6.0
export CLASSPATH=$CLASSPATH:$M2_HOME/lib
export PATH=$PATH:$M2_HOME/bin
保存,輸入以下命令使配置文件生效。
$ source /etc/profile
驗證是否安裝成功。
$ mvn -v
- 修改 maven 源爲阿里雲,以及倉庫默認存放路徑。這樣 maven 下載 jar 包的速度會快很多。
打開 maven 的配置文件
$ vim /opt/maven/apache-maven-3.6.0/conf/settings.xml
在 /home 目錄下生成 maven/repository 文件夾
<localRepository>maven/reposity</localRepository>
修改源
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
至此,Maven 安裝成功
參考資料:
啓動內網服務
在前面我們將 jupyter.frankfeekr.cn 反向代理(公網服務器 9000 服務,內網 5050)
這裏我們需要確保在內網電腦上,瀏覽器能夠訪問到 127.0.0.1:5050 這個服務。以我的 jupyter notebook 爲例:
這裏,我的內網服務已經啓動。接下來只需要啓動 lanproxy 客戶端即可。
運行 lanproxy client 服務
官方提供了兩種方式運行客戶端,一種方式是使用官方提供的 GO,另一種通過 Java 環境運行。本文采用主流的 Java 方式運行
- 克隆
lanproxy
代碼到本地電腦
$ git clone https://github.com/ffay/lanproxy.git lanproxy
- 打包
lanproxy
打包之前需要確保你安裝了maven
$ cd lanproxy
$ mvn package
- 修改配置文件信息
打包完成之後,客戶端文件會出現在distribution/proxy-client-0.1
目錄下,打開之後有是個文件夾:bin
、conf
、lib
和log
,配置信息在conf/config.properties
文件內,根據前面服務端的配置信息修改一下。
# 這裏是在lanproxy後臺配置的密鑰
client.key=e6a49a19b8024652ab4ff2210abf2c6a
# 配置ssl信息,根據服務端的配置填寫(enable = false 就不需要配置)
ssl.enable=false
ssl.jksPath=test.jks
ssl.keyStorePassword=123456
# 服務器的ip
server.host=120.92.10.120
#proxy-server ssl默認端口4993,默認普通端口4900
#ssl.enable=true時這裏填寫ssl端口,ssl.enable=false時這裏填寫普通端口
server.port=4900
- 啓動客戶端
客戶端信息配置完成之後就可以啓動客戶端了
# mac/linux使用這個
$ bash bin/startup.sh
# Windows 直接運行 bin/startup.bat
-
訪問測試
至此,即可通過公網域名 http://jupyter.frankfeekr.cn 訪問內網服務,實現內網穿透
當然你也可以通過公網 IP 和域名訪問,例如:http://120.92.10.120:9000 這種方式訪問!
- 停止客戶端
$ bash bin/stop.sh
lanproxy 網頁後臺服務
客戶端啓動服務後,後臺可查看狀態(在線 / 離線)
流量統計
2.4 內網電腦配置(GO 客戶端)
GitHub 客戶端主頁:lanproxy-go-client
不想安裝 Java 環境的可以選擇 Go
安裝Go環境安裝
1. buntu、Debian或Linux Mint安裝Go語言
基於 Debian的 Linux 發行版本都可以使用 apt-get 命令來進行安裝:
sudo apt-get install golang
要查看當前系統安裝的 Go 語言版本可以使用如下命令:
go version
由於 Go 代碼必需保存在 workspace(工作區)中,所以我們必需在 Home 目錄(例如 ~/workspace)創建一個workspace 目錄並定義 GOPATH 環境變量指向該目錄,這個目錄將被 Go 工具用於保存和編輯二進制文件。
mkdir ~/workspace
echo 'export GOPATH="$HOME/workspace"' >> ~/.bashrc
source ~/.bashrc
根據不同的需要,我們可以使用 apt-get 安裝 Go tools:
sudo apt-cache search golang
2. Fedora、CentOS或RHEL安裝Go語言
基於 Red Hat 的 Linux 發行版本都可以使用 yum 命令來進行安裝:
sudo yum update
sudo yum install golang
要查看當前系統安裝的 Go 語言版本可以使用如下命令:
go version
接下來還是在 Home 目錄(例如 ~/workspace)創建一個 workspace 目錄並定義 GOPATH 環境變量指向該目錄,這個目錄將被 Go 工具用於保存和編輯二進制文件。
mkdir ~/workspace
echo 'export GOPATH="$HOME/workspace"' >> ~/.bashrc
source ~/.bashrc
根據不同的需要,我們可以使用 yum 安裝 Go tools:
yum search golang
參考資料:如何爲Linux安裝Go語言 - Go語言中文網 - Golang中文社區
拉取 ffay/lanproxy-go-client 代碼
git clone https://github.com/ffay/lanproxy-go-client.git
安裝客戶端依賴包
cd lanproxy-go-client
sh build-release.sh
安裝後,這時候在目錄下會出現文件。
啓動客戶端
普通端口連接
# mac 64位
nohup ./client_darwin_amd64 -s SERVER_IP -p SERVER_PORT -k CLIENT_KEY &
# linux 64位
nohup ./client_linux_amd64 -s SERVER_IP -p SERVER_PORT -k CLIENT_KEY &
# windows 64 位
./client_windows_amd64.exe -s SERVER_IP -p SERVER_PORT -k CLIENT_KEY
SSL端口連接
# mac 64位
nohup ./client_darwin_amd64 -s SERVER_IP -p SERVER_SSL_PORT -k CLIENT_KEY -ssl true &
# linux 64位
nohup ./client_linux_amd64 -s SERVER_IP -p SERVER_SSL_PORT -k CLIENT_KEY -ssl true &
# windows 64 位
./client_windows_amd64.exe -s SERVER_IP -p SERVER_SSL_PORT -k CLIENT_KEY -ssl true
例如:
nohup ./client_linux_amd64 -s lp.thingsglobal.org -p 4900 -k 01c1e176d6ee466c8db717a8 &
命令參數:
GLOBAL OPTIONS:
-k value client key
-s value proxy server host
-p value proxy server port (default: 4900)
--ssl value enable ssl (default: "false", -p value should be server ssl port)
--cer value ssl cert path, default skip verify certificate
--help, -h show help
--version, -v print the version
三、總結
通過以上的配置,只要有一臺公網電腦,即可實現內網穿透功能。擺脫花生殼的域名端口限制,流量限制,帶寬限制。筆者的公網服務器爲 6M 帶寬,通過公網映射,文件下載測試大概在 800K/s - 1.5M/s 範圍,如果僅是普通的網站服務完全可以完美穿透。