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是一个问题,网络上有很多的相关讨论,但基本上经以上配置系统能够正常运行。

WordPress的迁移和反向代理

上一篇文章比较系统地讲了如何将wordpress迁移到apache环境下,特别提到apache能较好地完成web服务器任务,后来想到想在服务器上部署多个服务,并共用443端口,这种环境下较好的解决方案是安装Nginx来做反向代理。

一般web服务的反向代理配置较为简单,但wordpress在设计上有大量的动态代码,同时对内部数据的保护机制,使得它不能直接原位进行反向代理,直接反向代理将不能正确解释文件的链接,也不能正确渲染网站的样式。

所以再写一篇补充文章,简单谈谈wordpress手动迁移到apache的web服务器中,并用Nginx进行反向代理。

一、基础环境的搭建

包括操作系统、apache服务器、sql数据库、Nginx服务器等的安装调试,已在前面文章中有交待,可以参考。

另外需要准备域名和证书。

二、原始数据的打包上传

1、网站数据的打包上传

1.1 将原网站整个目录打包成压缩文件,wordpress.zip。

1.2 将 wordpress.zip 上传到服务器的 /var/www目录下

1.3 解压数据

unzip wordpress.zip

2、数据库的恢复

2.1 在原数据库中,将wordpress数据库导出为wordpress.sql文件

2.2 在原数据库中 新建mydb数据库,并将 wordpress.sql 文件导入其中

2.3 修改mydb数据库中的数据

2.3.1 将options字段中的siteurl和home的值修改为新使用的域名 https://aa.bb.com

2.3.2 将mydb 数据库中的网站链接全部替换为新的域名

update wp_posts set post_content=replace(post_content,'https://xxxxxx.com','https://aa.bb.com');

2.3.3 将 mydb 数据库 导出为 mydb.sql文件

2.4 将 mydb.sql文件 上传到服务器的 /home目录下

2.5 在服务器中新建wordpress数据库,并将 mydb.sql文件 导入其中

mysql
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
use wordpress
source /home/mydb.sql;

三、apache文件修改

1、修改apache2.conf

在其中增加根目录 /var/www/wordpress

2、修改ports.conf

在其中增加侦听端口 LISTEN 12356

3、修改sites-available目录中000-default.conf文件

在其中增加虚拟主机

4、重启apache2

systemctl restart apache2

四、修改网站设置

1、 修改wp-config.php

在define(‘WP_DEBUG’, false);语句之前,插入一段代码

可以参考附录文件的说明。

2、 修改wp-includes目录中functions.php文件

可以参考附录文件的说明。

五、配置Nginx

1、 创建wordpress反向代理配置文件

server

{

  listen 443 ssl;

    server_name aa.bb.com;

    index index.php index.html index.htm;

    root /var/www/wordpress;

    ssl_certificate    /etc/ssl/private/aa.bb.com.crt;

    ssl_certificate_key   /etc/ssl/private/aa.bb.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;

location / {

           proxy_pass http://aa.bb.com:123456; 

#以下代码使得web服务正确获得wordpress的链接地址

           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_redirect off;

      }

}

2、重启Nginx

systemctl restart nginx

六、浏览器中输入 https://aa.bb.com 验证网站能否正确运行。

上一篇文章是先用apache建好网站,并成功运行,是走一步看一步,这次是直接完成所有配置,一次性以反代方式运行网站。

附录:

1、Nginx反向代理实现Wordpress全站HTTPS TLS 1.3支持

2、Nginx使用Https反代WordPress