API服务监听 0.0.0.0 & 如何给本地localhost API使用HTTPS (API Gateway, SSH远程端口转发)

TL;DR

API 服务监听 0.0.0.0 IP地址,既可以被同一个局域网的主机通过改API主机的IP访问。

正文

后端开发中,各种API服务(比如,Django, Flask, Express.js)启动的时候,一般默认监听的都是127.0.0.1地址。

如果要使用DHCP分配的IP地址访问,可以把host改为0.0.0.0再启动API服务。这样同局域网的主机,比如说前端的同事就可以通过你的IP地址访问后端API了。

0.0.0.0的意思是分配给改主机的所有可能的IPv4地址。IPv6是::/0

可能分配给主机的IP地址是未知的,但是你启动API的时候是需要绑定一个IP地址的,如果你没有分配到IP地址,这个时候127.0.0.1就有用了,或者localhost也可以。

如果启动API的时候绑定不是你主机的IP会怎样?

你应该会有绑定失败,Django会抛出这个错误: Error: That IP address can't be assigned to.

所以,0.0.0.0就是有点类似通配符的效果。不需要指定Hard code 未知的地址。

竟然0.0.0.0这么方便,那些API框架怎么默认不使用?

我觉得是为了安全,0.0.0.0会直接让你服务器可能直接暴露在公网里面。一般开发过程中都是没有什么认证措施的,这个时候附近有个人端口扫描一下,可能就会泄露重要的资料。


为什么有了这个文章?

近期空闲时间在写Side project,需要暴露自己的API服务在公网,给一个SaaS服务回调。

当然我可以用ngrok,但是对比于4年前,这个服务现在越来越抠门。以前是可以单机多开,而且不限时长,现在玩了付费订阅制之后,限制越来越多。

我的解决方案是:

  1. API服务监听0.0.0.0端口,给路由器访问。
  2. 路由器做端口转发,让宽带公网IP的某个端口映射到本机API服务端口。
    1. 为什么不使用路由器DMZ?
    2. DMZ会直接暴露本机到公网。只使用端口转发所需的服务,这样安全点。

最后我把这个地址放到SaaS,即可访问http://58.123.123.123:8000/

延伸一下,如何给SaaS使用上HTTPS,而不是直接用本机公网地址?

方案一 AWS API Gateway Proxy :

SaaS Callback URL => AWS API Gateway => Public IP => Router Port forwarding => API (Listen 0.0.0.0)

  1. AWS API Gateway会给你分配一个HTTPS地址,你需要创建一个Stage才会有。
  2. 直接创建一个Resource,然后把所有路由都转发到本机的公网IP,比如上述的http://58.123.123.123:8000/
  3. 如果你不想使用AWS API Gateway分配的域名,你可以使用AWS ACM认证域名,然后在API Gateway创建一个漂亮的custom domain。
  4. 重要的是,上述的1 2 3都是免费的。如果超出了AWS free tier期限,AWS API Gateway是按需付费,零星的使用量基本上是免费的。
  5. ⚠️这个不是全程加密,API Gateway到本机的API服务之间的通信没有使用HTTPS。

方案二 本站Apache反向代理 + SSH远程转发(这个是我写这篇文章的时候想到的方法😂):

SaaS Callback URL => This WordPress Site Apache Reverse Proxy => SSH Remote forwarding => API (Listen on localhost)

  1. ✅ 这个是全程加密通信。
    1. SaaS到Apache是HTTPS,我还启用了Http2.0
    2. Apache到我本机的API服务是SSH。
  2. Apache的反向代理可以使用二级域名,然后创建一个VirtualHost。
  3. SSH使用的是远程转发。因为要远程主机访问本机服务,本机没有公网IP。

Apache VirtualHost代码:

<VirtualHost _default_:443>
  # 一个新的二级域名,记得配置DNS,还有SSL/TLS证书
  ServerName xx.adamliu.net
  SSLEngine on
  SSLCertificateFile "/opt/bitnami/apache2/conf/adamliu.net.crt"
  SSLCertificateKeyFile "/opt/bitnami/apache2/conf/adamliu.net.key"
  Protocols h2 h2c http/1.1

  ProxyPass "/"  "http://localhost:8000/"
  # 这句是让3xx之类的重定向地址可以被Apache捕获然后修改为apache的对外URL
  ProxyPassReverse "/"  "http://localhost:8000/"

  # Error Documents
  ErrorDocument 503 /503.html

</VirtualHost>

SSH远程端口转发:

# ServerAliveInterval和ServerAliveCountMax是为了保持session常驻
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=5  -R localhost:8000:localhost:8000 ubuntu@18.123.123.123

Leave a Reply

Your email address will not be published. Required fields are marked *