Nginx的四层转发实现多应用共用端口

前面因为wordpress的迁移写了两篇文章,想不到这是与之有关的第三篇文章了,一件事重复三遍,自己都觉得显得有点多余,但有些过程记录下来,也许对碰到类似问题的人有所帮助。

仅仅是一个web应用,自然不存在外部访问的端口问题,但如果是多个web应用或者还有其它应用呢?一个端口只能一个应用进行监听,如果用域名加端口方式,不存在问题,但网络上访问域名后拖个端口是不是显得不怎么高大上,最好是都用默认端口,这里就有共用端口问题。

仅仅是普通的共用端口也没有太大问题,用代理服务器,一般的http或https应用都能得到转发,用代理服务器的虚拟主机可以多个转发共同监听一个443端口,但如果某个应用必须工作在443端口呢,那么代理服务器就不能再用同一个端口。

本人想在一个服务器上布置多个应用,又想共用一个默认端口,碰到这个问题后在网络上找了一圈,直接的资料较少,只能多学习一下有关代理服务器的知识,从大量关于Nginx的四层负载均衡的讨论中得到启发。

Nginx的代理转发有四层和七层之分,七层是应用层的转发,这是一般常用代理模式,而四层转发则工作在网络的TCP层,利用IP和端口来转发客户端的请求,直接进行TCP数据包的转发,与一般的具体应用协议无关,这样有可能利用Nginx来转发各类的应用到同一个端口,从而满足各个应用对默认端口的要求。

1、Nginx加装stream、 stream_ssl_preread模块

Nginx 的四层转发需要利用 stream 模块来实现,较早版本的 Nginx 并不是默认同步安装该模块。

nginx -V 命令可以查看系统中是否已经带有该组件,出现以下–with-stream等文字,说明已经安装。ubbuntu20.04在安装nginx时会自动加入以上模块。

如果没有该模块,需要进行编译安装,网络上有详细教程。

2、配置nginx.conf文件

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
	worker_connections 1024;
}
stream {  
  map $ssl_preread_server_name $backend_name { 
    aa.cc.com web1; 
    bb.cc.com web2;
  } 
  upstream web1 { 
    server 127.0.0.1:20000; 
  } 
  upstream web2 { 
    server 127.0.0.1:20001;
  } 
  server { 
    listen 443 reuseport; 
    listen [::]:443 reuseport; 
    proxy_pass $backend_name; 
    ssl_preread on; 
  }
}
http {
........

http部分可以保持默认,一般nignx.conf文件只有头部和http两部分,这里需要增加一个stream部分。

3、配置conf.d中的反向代理

新建web1.conf文件

server
{
    listen 20000 ssl;
    server_name aa.cc.com;
    index index.php index.html index.htm default.php default.htm default.html;
    root /var/www/html1;
    ssl_certificate    /etc/ssl/private/aa.cc.com.cer;
    ssl_certificate_key   /etc/ssl/private/aa.cc.com.key;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
  
location / {
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
             proxy_set_header Host $host;
             proxy_pass http://aa.cc.com:8080;
             proxy_redirect off;

      }
}

4、几点讨论

4.1 以上配置说明,真实的web服务在本地服务器的8080端口,而nginx的反向代理在20000端口进行监听, nginx的四层转发在443端口进行监听。所有的请求从443进入,利用SNI的区别被直接从四层转发到nginx的代理服务器上不同的监听端口,代理服务器再根据对应的IP和端口转发到真实的后端服务器上。

4.2 这里利用四层转发解决共用端口问题,同时利于nginx的反向代理隔离后端服务器,有利用增强安全性。如果不代理,因为四层转发,后端服务器将直接面对客户端的请求,在大型项目上不利于系统的稳定可靠。

4.3 经过多重转发和代理,后端服务正确获得客户端的真实IP是一个问题,网络上有很多的相关讨论,但基本上经以上配置系统能够正常运行。