内网穿透服务可以帮助我们从公网访问本地计算机上的服务与资源,对于开发人员来说是一款很实用的工具。虽然市面上有一些免费的穿透服务,但是用起来不仅慢,还有各种限制,想要更好的体验则需要使用付费服务。Ngrok(v1版本)是一个开源项目,使用Ngrok能简单、快速地实现内网穿透服务,最重要的是免费!免费!免费!(如果你有一台服务器的话)。

准备工作

  • Go语言

    https://dl.google.com/go/go1.12.1.linux-amd64.tar.gz

    注意一定要使用低版本

  • Ngrok源码

    https://github.com/inconshreveable/ngrok/archive/refs/tags/1.7.1.zip
  • 解析域名
    图片1.png
    我这里使用三级域名,因为二级域名有其他站点使用,*.rmt.yourdomain.com为三级域名,rmt.yourdomain.com为Ngrok通信使用

安装Go语言

要使用低版本,我这里使用源码安装

  • 解压源码并移动到/usr/local/目录

    tar -zxvf go1.12.1.linux-amd64.tar.gz
    mv go /usr/local/
  • 添加环境变量

    cd ~
    vim .bashrc

    向.bashrc文件中添加如下内容

    export GOPROXY=https://goproxy.io,direct
    export GOROOT=/usr/local/go
    export PATH=$PATH:/usr/local/go/bin

    更新环境变量

    source ~/.bashrc
  • 验证是否安装成功

    go version

    如果有版本信息打印出来就成功了

生成tls证书

  • 添加NGROK_DOMAIN环境变量

    vim ~/.bashrc

    添加如下内容

    export NGROK_DOMAIN="rmt.yourdomain.com"

    更新环境变量

    source ~/.bashrc
  • 生成证书

    cd /usr/local/go
    mkdir cert
    cd cert
    
    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

编译生成可执行文件

Linux服务端和Windows客户端

GOOS=linux GOARCH=amd64 make release-server
GOOS=windows GOARCH=amd64 make release-client

其他平台

Linux 32位:GOOS=linux GOARCH=386
Linux 64位:GOOS=linux GOARCH=amd64
Windows 32位:GOOS=windows GOARCH=386
Windows 64位:GOOS=windows GOARCH=amd64
MAC 32位:GOOS=darwin GOARCH=386
MAC 64位:GOOS=darwin GOARCH=amd64
ARM:GOOS=linux GOARCH=arm

生成的可执行文件位于bin目录下

报错解决

  • code.google.com/p/log4go

    package code.google.com/p/log4go: unrecognized import path "code.google.com/p/log4go" (parse https://code.google.com/p/log4go?go-get=1: no go-import meta tags ())
    make: *** [Makefile:8:deps] 错误 1

    解决办法:将文件src/ngrok/log/logger.go中的code.google.com/p/log4go改为github.com/alecthomas/log4go

  • github.com/rivo/uniseg

    package github.com/rivo/uniseg: found packages uniseg (doc.go) and main (gen_breaktest.go) in /root/software/ngrok-1.7.1/src/github.com/rivo/uniseg
    make: *** [Makefile:8:deps] 错误 1

    解决办法:使用低版本rivo/uniseg,如v0.1.0,解压替换src/github.com/rivo/uniseg中的文件

  • github.com/gorilla/websocket

    src/github.com/gorilla/websocket/client.go:408:15: undefined: io.NopCloser
    src/github.com/gorilla/websocket/client.go:426:14: undefined: io.NopCloser
    src/github.com/gorilla/websocket/conn.go:808:25: undefined: io.Discard
    src/github.com/gorilla/websocket/conn.go:1113:11: undefined: io.ReadAll
    src/github.com/gorilla/websocket/server.go:177:23: undefined: http.NewResponseController
    src/github.com/gorilla/websocket/tls_handshake.go:9:19: tlsConn.HandshakeContext undefined (type *tls.Conn has no field or method HandshakeContext)
    make: *** [Makefile:17:client] 错误 2

    解决办法:使用低版本gorilla/websocket,如v1.4.1,解压替换src/github.com/gorilla/websocket中的文件

启动服务端

Ngrok通信使用的端口只要没被占用就可以,这里以9500端口为例

./ngrokd -log=stdout -domain="rmt.yourdomain.com" -httpAddr=":1080" -httpsAddr=":10443" -tunnelAddr=":9500"

请在服务器防火墙、云服务器安全组中放行9500端口。有如下输出,没有报错就是成功了

[16:22:24 CST 2023/09/12] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[16:22:24 CST 2023/09/12] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds
[16:22:24 CST 2023/09/12] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:1080
[16:22:24 CST 2023/09/12] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:10443
[16:22:24 CST 2023/09/12] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:9500

启动客户端

  • 配置文件ngrok.cfg

    server_addr: "rmt.yourdomain.com:9500"
    trust_host_root_certs: false
    tunnels:
        site:
            proto:
                http: 80
            subdomain: site
        win:
            proto:
                tcp: 3389
            remote_port: 33890

    这里配置了两个隧道,分别是80端口的http服务、3389端口的Windows远程连接。启动客户端

    ngrok.exe -config=ngrok.cfg start site win

    图片2.png

访问服务

  • Windows远程
    图片3.png
  • 站点
    由于我的服务器中安装了宝塔面板,所以我直接在宝塔中创建站点,并在站点配置中添加如下Nginx配置。其他环境大同小异,配置好代理就行。站点配置文件中添加一下代理配置并保存

    # 转发到1080端口
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host:1080;
        proxy_pass_header Server;
        proxy_redirect off;
        proxy_pass http://127.0.0.1:1080;
    }

    图片5.png
    图片4.png

注意

  • Ngrok v1版本不再维护,请谨慎使用
  • 无法连接时请首先检查防火墙和安全组
  • 请务必添加NGROK_DOMAIN环境变量
  • 服务端和客户端需要一起编译生成

标签: Nginx, Go, 内网穿透

添加新评论