美文网首页
NGINX+SSH 暴露本地端口

NGINX+SSH 暴露本地端口

作者: 寂寞的原子 | 来源:发表于2019-05-19 21:23 被阅读0次

我们在 web 开发中,经常会有暴露本地端口的需求:

  • 网站开发到一半,希望分享一下当前成果;
  • 某app小程序的开发,只能通过生产环境默认端口进行接口调试;
  • 通过公网进行联调;
  • ……

ngrok 的出现让我们可以通过服务器的中转,快速暴露本地端口。那么 ngrok 方案有什么不足呢?

  • ngrok 在客户端和服务端都要安装;
  • ngrok 已经闭源,开始走商业化发展路线,不再适合我等屁民使用;
  • 使用自定义域名有诸多不便。

定制方案

我尝试寻找一个简单的方案,来实现部分 ngrok 的能力,满足我们开发调试过程中的大部分需求。

内网穿透到公网

SSH 提供了加密的端口流量转发能力,可以用来快速实现这个步骤。通过 SSH 可以把一个本地端口和远程端口映射起来,打通流量隧道。先看一下 SSH 的相关文档:

-N      Do not execute a remote command.  This is useful for just forwarding ports.

-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket
-R [bind_address:]port
        Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.

通过指定 -N,我们可以让 SSH 不执行远程命令,而只用于转发流量。

通过指定 -R 远程地址:本地地址,即可实现端口流量转发。

举个栗子:

$ ssh -NR 2333:localhost:8080 server

即把本地的 8080 端口映射到服务器的 2333 端口,由于没指定 bind_address,这个端口默认会绑定到本地环回地址(localhost)上,必须通过反向代理才能从外部访问。

我们也可以绑定 bind_address0.0.0.0,让端口直接暴露到外部:

$ ssh -NR 0.0.0.0:2333:localhost:8080 server

这要求我们开启 OpenSSH 的 GatewayPorts 配置。这种情况下,我们就可以直接从外部访问 server_address:2333 了。

但是,为了提供缓存、资源压缩、权限校验、域名控制等能力,一般来说我们更推荐使用 NGINX 反向代理来暴露端口。通过 NGINX 统一管理,可以在一个端口上服务多个站点,通过域名区分站点,这样我们就可以从默认端口提供服务,地址看上去更自然,同时还能满足某些 app 的特殊要求。

绑定自定义域名

如果没有固定的域名,我们每次开启服务,都需要提供一个新的 address:port 或者 ip:port 地址,这显然是很不友好的。ngrok 的免费版提供的就是一个随机域名。而通过 NGINX,我们可以很轻松地定制一个域名映射规则,然后只需要按照规则开启服务,就可以通过想要的域名访问到。

这里有一个大前提,首先我们要有个域名,而且域名要泛解析到我们的服务器,如 *.gerald.win 添加 CNAME 记录到 gerald.win。只有解析到了我们的服务器,NGINX 才可以有发挥的空间。

举个栗子,约定域名 tunnel2333.gerald.win 反代到服务器的 localhost:2333,以此类推,我们只要在打通隧道时映射到同样的端口号,就可以用同样的域名访问。NGINX 配置如下:

server {
  listen 80;
  server_name "~^tunnel(?<port>\d+)\.gerald\.win$";

  location / {
    proxy_pass http://127.0.0.1:$port;
    proxy_set_header Host      $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_intercept_errors on;
  }
}

同样的,我们也可以通过 unix socket 文件名的约定来实现更加定制化的子域名,这里就不详细展开了。

支持HTTPS

随着大家对网络安全的重视,HTTPS 几乎已经成了网站的标配,很多接口都要求服务端必须为 HTTPS 协议,这也在无形中提高了我们的开发调试门槛。通过服务器的转发,这个问题也迎刃而解。

作为普通开发者,我们就不考虑购买昂贵的 HTTPS 证书了。好在良心产品 Let's Encrypt 从 ACME v2 开始已经支持泛解析了,于是 Let's Encrypt 一把梭搞定。这里强烈推荐国人开发的脚本 acme.sh,证书生成过程不再赘述。

有了证书,我们再配置一下提供 HTTPS 服务的 NGINX 配置,还可以给 HTTP 协议访问的页面做个 301 跳转:

server {
  listen 80;
  server_name "~^tunnel(?<port>\d+)\.gerald\.win$";

  location / {
    return 301 https://$host$request_uri;
  }
}

server {
  listen 443 ssl http2;
  server_name "~^tunnel(?<port>\d+)\.gerald\.win$";

  ssl_certificate      /home/gerald/ssl/fullchain.cer;
  ssl_certificate_key  /home/gerald/ssl/gerald.win.key;

  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout  5m;

  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers   on;

  location / {
    proxy_pass http://127.0.0.1:$port;
    proxy_set_header Host      $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_intercept_errors on;
  }
}

这样我们就实现了 HTTPS 协议的支持,而且无需为每个新域名单独配置。

不足

与 ngrok 相比,我们的简化方案其实还是有很多不足的,比如缺失了强大的 inspector,无法动态展示当前连接的用户、访问的页面和流量。这些功能属于锦上添花了,理论上都可以在客户端进行实现,以后可以考虑增强一下。

总结

原理总结如下:

  • SSH 打通隧道
  • NGINX 反向代理
  • Let's Encrypt 实现泛解析 HTTPS 证书

通过 SSH + NGINX,我们基本实现了本地端口的暴露,完美地支持了通过 HTTPS 协议来调试本地的应用。

相关文章

  • NGINX+SSH 暴露本地端口

    我们在 web 开发中,经常会有暴露本地端口的需求: 网站开发到一半,希望分享一下当前成果; 某app小程序的开发...

  • dubbo原理:服务暴露

    服务暴露分为两种:本地暴露(暴露在JVM中,不需要网络通信);远程暴露(将ip,端口等信息暴露给远程客户端,调用时...

  • Docker容器内部署静态网站

    设置容器的映射端口-P 暴露所有端口进行映射-p 暴露指定容器端口 四种方式 示例: Nginx部署步骤: 创建映...

  • 5. 调试利器 - 端口转发 - ssh隧道技术

    说明 使用技术:** SSH隧道**端口转发分为 本地端口转发 和 远程端口转发。本地端口转发:将远程的端口映射到...

  • eos常用内容

    一、eos 版本: 2:服务器,端口:80803:本地, 端口:80804:本地, 端口:8888 二、eos...

  • 内网端口的转发

    端口的转发 一:linux系统下: 1、本地端口转发本地端口 iptables -t nat -A PREROUT...

  • 将服务器上的文件传输到本地

    nc -l4 端口 > 文件 // 本地执行nc 本地IP 本地端口 < 文件 // 服务器执行

  • nginx 配置

    1、nginx访问配置 2、代理本地3000端口到3066端口 3、代理网络端口和本地端口到3066解决跨域问题 ...

  • Docker网络管理与容器互联

    暴露端口 容器互联 网桥 跨主机容器互联网桥Open vSwitchweave 暴露端口 容器运行起来后,其内部的...

  • udp测试远程端口

    nc 命令可以满足需求:nc -p 本地端口 -u 远程host 远程端口 -p 指定绑定本地哪个端口-u 使用 ...

网友评论

      本文标题:NGINX+SSH 暴露本地端口

      本文链接:https://www.haomeiwen.com/subject/anqczqtx.html