# 环境搭建
# 目的
在更新 nginx upstream pool 时,一般方案是更新 nginx 配置文件,然后 reload nginx, 在 nginx 繁忙时会导致 worker process 长久处于 shutdowning, 并且频繁的 upstram 可能导致 nginx 芭比 Q。
所以我们这里需要解决的问题就是怎么不 reload 就能实现修改 nginx 配置。
以下环境搭建是基于 Ubuntu 的。
# 下载 tar 包
到官方下载 tar 包 http://tengine.taobao.org/download.html
这里下载最新的 2.3.3
wget http://tengine.taobao.org/download/tengine-2.2.3.tar.gz |
# 运行环境检测脚本,安装 nginx 依赖库(pcre、openssl、zlib)
提前安装需要的依赖(也可以先运行 configure,根据缺少的逐步安装)
apt-get install gcc -y | |
apt-get install libpcre3 libpcre3-dev -y | |
apt-get install openssl libssl-dev -y | |
apt-get install zlib1g-dev -y |
解压 tar 包后进入目录,运行目录下的 configure 文件
此时如果系统缺少必要的组件,会报错。我们只需要根据报错信息进行解决即可。(如图,代表缺少 gcc)
这里要求 gcc,所以我们先安装安装。
安装完毕后再次执行,发现新的报错。
根据报错进行安装,这里是缺少 PCRE,再次运行,缺少 openssl,继续安装。
此时再次运行,缺少 zlib 库,再次下载。
最后没有报错了,环境检查没问题。如下图,是安装的默认参数。
这里 jemalloc 是内存优化的,需要的就装,不需要的就不管。
这里给上 jemalloc 的安装操作(根据需求决定是否要加),首先下载 jemalloc,然后进行解压即可,其他不需要操作,到后面的时候再操
wget https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 | |
tar -jxvf jemalloc-5.2.1.tar.bz2 |
# 安装 tengine
到这里正式开始安装。安装完成后,会在 /usr/local/nginx 下看到 tengine 的安装文件(默认情况下,如果没设置了 configure --prefix=/xx/xx 的话)
./configure --prefix=/usr/local/tengine --without-http_upstream_keepalive_module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-stream --with-http_realip_module --add-module=./modules/ngx_http_upstream_* |
PS:如果需要加 jemalloc 的话,加上参数(后面的是解压的路径) --with-jemalloc=~/jemalloc-5.2.1/
然后就可以编译了,完成后就会在前面我们设置的安装目录下找到服务。
make && make install |
这里就其实和 nginx 一样,只是这里没有注册成服务,所以需要到安装目录下去执行二进制文件,当然我们也可以把他 cp 到 /usr/local/sbin 上就可以了。
/usr/local/nginx/sbin/nginx -V |
/usr/local/nginx/sbin/nginx # 启动 nginx,不需要参数 |
此时访问 80 端口即可看到如下界面
# 配置
略,就和 nginx 一样。
# dyups 动态更新 upstream
为了针对 nginx 不能动态修改配置文件这一痛点,dyups 应运而生,这个模块能够实现动态修改配置。他的原理其实就是相当于把一个配置文件给加到了动态内存中,然后通过 web 进行管控从而实现动态修改。
PS:因为我在前面 build 的时候加入了 upstream 模块,所以直接用就行。
如图,这里就是在 8000 端口监听了 dyups 的控制端,然后我们就可以通过访问这个端口从而对内存中的 conf 文件进行修改了。
下面的配置实现的功能就是一个将流量根据 upstream 转发的配置
使用 allow 和 deny 可以设置这个接口允许访问的 ip
那么 upstream 是什么呢?在配置文件中他长这样,如果我们设置了如下的配置,那么对于上述的转发配置,我们的 host 如果是 hots1,流量就反代到 8088 端口。如果 host 是 host2,则反代到对应的下面那个端口。
那么我们怎么动态更新这个 upstream 呢?前面也讲了,dyups 通过监听一个端口实现对内存中的一个 upstream 配置文件修改,因此我们只需要调用这个 web 接口即可。
GET 方法(读)
- /detail #获取全部 upstream 的详细信息
- /list #获取 upstream 的列表
- /upstream/<name> #查询指定 upstream 的信息
POST 方法(写)
- /upstream/<name> #修改 upstream 的信息(如果不存在这个 upstream,则增加)
DELETE 方法(删除)
- /upstream/<name> #删除这个 upstream
查看当前 upstream 的细节。 GET 方法
修改指定 upstream (如果没这个 name,就会增加,有就会修改)
删除指定 upstream
# 效果展示
这里,我们本地 docker 开启了两个不同的服务,接着我们尝试通过不同的域名来实现访问这两个服务。
这里我们想要的结果是动态修改配置,使得访问 host1 则能到达 50001,访问 host2 到达 50002 .
因此我们只需要加两个 upstream 即可。
如图,向 dyups 管理端发送如下两个数据包即可完成添加 upstream。
curl -d "server 127.0.0.1:50001;" 192.168.5.179:8000/upstream/1.aaa.com #对应的 curl 命令 |
此时访问 1.aaa.com 和 2.aaa.com 即可达成目的。
# 题外话,使用 nginx 做隧道
Q:既然 nginx 是个反代服务器,那么是不是也能够实现其他协议的隧道代理功能呢。
A:nginx 本身只是 web 服务器,在默认情况下是不支持其他协议的反代的。但 nginx 在 1.9.0 开始,新增了一个 stream 模块,可以用来实现其他协议的转发、代理和负载。
# 查看是否存在 stream 模块
stream 模块默认情况下是不会编译到 nginx 中的,所以在编译 nginx 的时候需要带上参数 --with-stream
nginx -V #查看 nginx 的详细信息,看是否存在 stream 模块 |
# 使用 steam 进行端口映射(反代)
这里我们选择让 nginx 反代内网的一个 22 端口
只需要在 nginx 配置文件中添加 stream 键值 (和 event、http 同级) 即可。
如下配置的意识是在 nginx 监听本地 3389 端口,把这个端口的流量给代理到 upstream aaa 上,而
aaa 的目标又是内网的一个 ssh 端口
因此这里最终结果就是访问 nginx 服务器的 3389 等价于访问内网的 ssh 了。
# 使用 nginx 做 socket 隧道 (正向代理)
A: 既然 nginx 能够实现反代,那么我们肯定不想止步于此,我们想让 nginx 在渗透周期中做更多的事情,比如做 socket 隧道?
Q: 查遍网上所有资料,nginx 本身不支持,需要第三方模块。但是我找到的两个第三方模块在编译的时候都报错了。只能说结局待定了。
https://github.com/zmkeil/ngx_socks.git