[原创]搭建自己的 Ngrok 服务器, 并与 Nginx 并存
Ngrok 是一个内网穿透工具, 用来将内网的一些服务器暴露到公网上, 目前支持 HTTP 和 TCP 端口转发.
Ngrok 官方提供的服务器因为一些原因导致可用率不高, 但是他们开源了 1.x
版本的服务器端代码(目前最新是 1.7
), 这样就可以自己搭建了.
Ngrok Server 端部署
这个比较简单, 参考官方的文件就可以, 步骤无非就是: 拿到代码, 安装 go, 进行编译.
文档地址: https://github.com/inconshreveable/ngrok/blob/master/docs/DEVELOPMENT.md
编译完成后, 执行 ngrokd -h, 输出如下:
Usage of bin/ngrokd:
-domain="ngrok.com": Domain where the tunnels are hosted
-httpAddr=":80": Public address for HTTP connections, empty string to disable
-httpsAddr=":443": Public address listening for HTTPS connections, emptry string to disable
-log="stdout": Write log messages to this file. 'stdout' and 'none' have special meanings
-log-level="DEBUG": The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR
-tlsCrt="": Path to a TLS certificate file
-tlsKey="": Path to a TLS key file
-tunnelAddr=":4443": Public address listening for ngrok client
参数比较简单, 指定域名, http 端口, 日志, ssl 证书, 隧道端口.
这里有个问题就是, 80, 443 已经让给 nginx 使用了, 虽然 ngrok 能指定到其它端口, 但是在客户端连接后:
一个是 https 识别错误, 一个是访问的时候加端口麻烦, 就算用 nginx 再次代理, 但是客户端显示的端口是没有变化的.
Docker 部分
如果你的服务器有多个 IP, 也可以 Nginx 和 Ngrok 分别监听不同的 IP, 就可以省去 Docker 了.
然后我想到了 Docker, 既然服务端给什么端口, 客户端就显示什么端口, 那么就用 Docker 来欺骗 Ngrok 好了.
找了下 Docker Hub, 大部分都是客户端, 部分服务器端也不是很满意, 那就自己写了个 Dockerfile 编译下吧:
FROM ubuntu:14.04
MAINTAINER fengqi xxx@gmail.com
ENV NGROK /opt/ngrok
ENV DOMAIN ngrok.fengqi.me
EXPOSE 80 443 4443
COPY run.sh $NGROK/
COPY bin/ngrokd $NGROK/
COPY ngrok.fengqi.me.crt $NGROK/ssl.crt
COPY ngrok.fengqi.me.key $NGROK/ssl.key
RUN chmod +x $NGROK/run.sh
CMD $NGROK/run.sh
run.sh 内容:
#!/bin/bash
/opt/ngrok/ngrokd -tlsCrt /opt/ngrok/ssl.crt -tlsKey /opt/ngrok/ssl.key -domain ngrok.fengqi.me
内容比较简单, 以 Ubuntu 14 构建, 然后把外面编译好的 Ngrokd 和 SSL 证书复制进去.
我的 SSL 是用的免费证书, 没有通配版, 所以 https://*.ngrok.fengqi.me
是自签名证书.
如果你想测试我提供的 https, 需要先本地安装并信任我的跟证书 Fengqi Global CA
我在自签名证书时, 全部是使用这个跟证书颁发, 所以只需要本地信任一次就可以了.
然后在放 Dockerfile 的目录下运行 docker build -t fengqi/ngrokd .
等等执行完成.
执行 docker images
查看下现在的容器:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
fengqi/ngrokd latest fdf8ca983ed9 1 minutes ago 198.4 MB
ubuntu 14.04 91e54dfb1179 13 days ago 188.4 MB
可以看到已经正常编译完成, 然后启动这个容器:
docker run -d -p 127.0.0.1:8080:80 -p 127.0.0.1:8081:443 -p 4443:4443 fengqi/ngrokd:latest
这里把容器里的80, 443, 4443 端口映射到本地, 后面再通过 Nginx 反代提供到公网.
检验下效果:
root@fengqi-Vultr:~# telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
^]quit
telnet> quit
Connection closed.
root@fengqi-Vultr:~# telnet 127.0.0.1 8081
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
^]quit
telnet> quit
Connection closed.
root@fengqi-Vultr:~# telnet 127.0.0.1 4443
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
^]quit
telnet> quit
Connection closed.
看起来没什么问题.
Nginx 部分
Nginx 只需要建立一个 http server, 把请求转发到 Docker 里面的 Ngrokd 就行了.
map $scheme $proxy_port {
"http" "8080";
"https" "8081";
default "8080";
}
server {
listen 80;
listen [::]:80;
listen 443;
listen [::]:443;
server_name ngrok.fengqi.me *.ngrok.fengqi.me;
location / {
proxy_pass $scheme://127.0.0.1:$proxy_port;
}
ssl on;
ssl_certificate /opt/ngrok/ngrok.fengqi.me.crt;
ssl_certificate_key /opt/ngrok/ngrok.fengqi.me.key;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log off;
log_not_found off;
}
这里没有做什么优化, 就是转发下请求. 这时客户端再次链接时就正常了:
因为需要开机就启动这个容器, 可以把启动命令放到 /etc/rc.local
里面.
使用第三方 Ngrok 服务器
使用我提供的 Ngrok 服务器的方法是, 在 ~/.ngrok
下写入以下内容:
server_addr: "ngrok.fengqi.me:4443"
trust_host_root_certs: true
[...]搭建自己的Ngrok服务器, 并与Nginx并存[...]
https用的是ngrok服务器编译出来的证书,还是免费的证书
都可以, 现在 letsencrypt 也有 wildcard 了
请问,我想在服务器上使用ngrok客户端生成的https,来达到内网搭建https,外网通过域名访问https,只要我监听相应端口(按照本文,应该是80端口)就可以了吗?
对的, https 由 ngrok 来
相当感谢,这个帖子帮助我解决了大问题,并且开始学习了docker 真是入了深坑了。
请问下大神,linux下需要安装证书?
对,因为四级子域是不固定的,所以需要通配符,但是我的 SSL 证书是免费版不支持通配符,所以只能自颁发了。
非常感谢, 解决大问题了!
不用客气 :-)
你好 windows下如何使用你的ngrok服务呢?
一样的,下载 win 的客户端,安装我的证书,cmd 下运行命令就好了。
非常感谢,配置好了很方便,省了一台服务器和一个ip地址
不用客气 :-)