前言
最近常和Nginx打交道,就诞生了编写Nginx专栏的想法;另一方面则是博客也荒废好长时间了,想要拾起来,重新出发啦。
预计在五月前会更新完我目前关于Nginx专栏相关的博客,后续的话,则需要看情况和时间去更新更多使用的博客啦。
上一次写博客还是在参与年终总结的活动,要是说写技术文的话,那需要追溯到7月前的 关于 Spring Integration 你知道多少,包含集成MQTT案例讲述及源码
停更了较为漫长的一段时间吧,从去年心里开始蹦出换工作的想法,一直到入职新的公司,再一直到现在,写博客的频率就较低了,可以说人同时也进入了一种较为迷茫的状态,有种茫茫然活着的感受吧。
一开始动手敲下文字,就不可避免想要说些自己无人可以诉说的话,那些别人听去可能觉得矫情又或者觉得无语的话,只好通过这种方式来表达啦。
说回文章本身吧,这个通过 Nginx 代理 SSH 端口的需求,严格说起来是我自己折腾的。
项目单位上有一台服务器,外部访问是通过公网IP做端口映射来实现的,而一些服务是没有映射端口的,只能够先通过远程软件连接到项目单位的主机,再通过ssh连接到服务器,去查看日志。(这就非常折磨人啊)
项目单位上不允许直接映射22端口,我才想了这个的,但是即使通过其他端口映射,也一定要做好安全防护,白名单等,以免出现安全问题
一、Nginx常见使用方式
可能大部分朋友听到Nginx时,所能想到的使用方式大致就是:
1、nginx实现反向代理
2、实现动静分离
3、nginx部署vue项目
4、nginx解决跨域问题
5、nginx配置ssl证书
等等,当然还有一些其他的使用方式,但上述列出来的都是较为常见的,可能也有很多朋友接触过。
实话实说,在我没遇上我自己这个需求时,我根本没想过要使用 Nginx 来实现 ssh 的代理,也根本不知道 Nginx 可以实现 ssh 的代理。
补充:
上面所有列出来的使用方式都是使用Nginx来实现七层代理(也有叫七层负载均衡),而实现ssh的代理,则是要实现四层代理(也有叫七层负载均衡的),Nginx本身并不直接支持tcp的代理,需要借助扩展模块来进行实现。
二、七层负载均衡和四层负载均衡
最后还是决定写一下这个章节啦,可以更详细的知道 nginx 在此时的作用。
七层负载均衡
七层代理主要工作于OSI模型的应用层,应用层主要用来处理消息内容的。比如,HTTP便是常见的七层协议。
七层负载均衡服务器起到了反向代理的作用,Client端要先与七层负载均衡设备三次握手建立TCP连接,把要访问的报文信息发送给七层负载均衡。
七层负载均衡器基于消息中内容( 比如URL或者cookie中的信息 )来做出负载均衡的决定。之后,七层负载均衡器建立一个新的TCP连接来选择上游服务并向这个服务发出请求。
使用七层负载均衡的设备经常被用于反向代理。
比如我们常常使用Nginx来代理单体的Java服务,比如类似下面这种常见配置:
bash
location /spider {
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.1.28:6790/spider;
}
看完配置文件,应该可以更好的理解这句"七层负载均衡器基于消息中内容( 比如URL或者cookie中的信息 )来做出负载均衡的决定"的话了吧
四层负载均衡
四层代理主要工作于OSI模型中的传输层,传输层主要处理消息的传递,而不管消息的内容。TCP就是常见的四层协议。
四层负载均衡只针对由上游服务发送和接收的网络包,而并不检查包内的具体内容是什么。 四层负载均衡可以通过检查TCP流中的前几个包,从而决定是否限制路由。
因此,四层负载均衡的核心就是IP+端口层面的负载均衡,不涉及具体的报文内容。
比如下面这个就是我编写的代理ssh端口的配置文件:
bash
stream {
allow 111.11.11.11;
deny all;
proxy_timeout 1d;
proxy_connect_timeout 30;
upstream ssh-proxy {
server 192.168.1.19:22;
}
server {
listen 9999 ;
proxy_pass ssh-proxy;
}
}
在这个配置文件中可以看出,nginx 只是监听了 9999 端口,有消息的话,就将它传递给 proxy_pass 指定的服务中去。即只受IP+端口的影响,不受消息体的影响。
三、Docker Nginx 安装 Stream 模块
Nginx 本身并没有直接开启四层代理,需要在编译的时候安装指定的模块来实现。
nginx-1.9.0 发布,该版本增加了stream 模块用于一般的TCP 代理和负载均衡,ngx_stream_core_module 这个模块在1.90版本后将被启用。但是并不会默认安装, 需要在编译时通过指定 --with-stream 参数来激活这个模块。
Stream 模块使得 Nginx 可以像 TCP/UDP 代理一样工作,并且支持负载均衡、反向代理、SSL 加密等功能。后续将介绍如何在 Docker 容器中安装并配置 Nginx 的 Stream 模块。
前置环境:docker
我在ubuntu上直接编译过不少程序,mqtt、nginx、opencv、zlm等等,实话实说,非必要,真一点也不建议在宿主机上编译什么程序,因为你不知道要踩多少坑....
对如何直接在ubuntu上编译Nginx感兴趣的话 ,点赞过三十,我到时候更一篇如何在ubuntu宿主机上编译nginx的博客,哈哈哈
不过我更建议使用Docker来实现这些操作,一方面是资源隔离,另外一方面是docker真的方便,认识大部分开发者,感觉都有使用到Docker。
后续的话,需要一点点docker相关的知识,如果都不行的话,至少得安装好docker,然后跟着贴命令就好。
docker 安装命令
bash
sudo apt update
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt install docker-ce
#到此安装完成, 可以输入 sudo docker --version 或者 sudo docker run hello-world 测试是否安装成功
#如果您想免sudo进入docker的话, 直接输入以下命令,亲测:
sudo groupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp - docker
#注意:最后一步是必须的,否则因为 groups 命令获取到的是缓存的组信息,刚添加的组信息未能生效,所以 docker images 执行时同样有错。
# 如果还是不行请尝试
sudo chmod o+rw /var/run/docker.sock
3.1、编写 Dockerfile 文件
编写Dockerfile的作用是制作镜像,这方面的知识可能需要大家去了解docker的简单概念,不再赘述了。
dockerfile
FROM nginx:latest
RUN apt-get update && apt-get install -y \
build-essential \
libpcre3-dev \
zlib1g-dev \
wget
WORKDIR /usr/src/nginx
RUN wget https://nginx.org/download/nginx-1.22.1.tar.gz \
&& tar -xzvf nginx-1.22.1.tar.gz
WORKDIR /usr/src/nginx/nginx-1.22.1
RUN ./configure --with-stream && make && make install
ADD nginx.conf /etc/nginx/nginx.conf
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 9888
STOPSIGNAL SIGTERM
CMD ["nginx","-g","daemon off;"]
比较重要的就这一句了,在编译nginx的时候,编译时通过指定 --with-stream 参数来让nginx实现tcp四层负载均衡。
bash
RUN ./configure --with-stream && make && make install
3.2、Nginx 配置文件
将 nginx.conf 配置文件置于和Dockerfile 同一个目录下。
bash
user root;
worker_processes 1;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events
{
use epoll;
worker_connections 1024;
}
http
{
include mime.types;
default_type application/octet-stream;
sendfile on;
#aio on;
directio 512;
output_buffers 1 128k;
log_not_found off;
keepalive_timeout 65;
server_tokens off;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
gzip on;
gzip_comp_level 6;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_disable "MSIE [1-6].(?!.*SV1)";
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/javascript application/json;
log_format main '{'
'"@level": "info",'
'"@remote": "$remote_addr",'
'"@forwarded": "$http_x_forwarded_for",'
'"@server": "$server_addr",'
'"@hostname": "$host",'
'"@timestamp": "$time_iso8601",'
'"@spend":"$request_time",'
'"@request": {'
'"@protocol": "$scheme",'
'"@host": "$host",'
'"@path": "$request",'
'"@header": {'
'"@User-Agent": "$http_user_agent"'
'}'
'},'
'"@response": {'
'"@statusCode": "$status"'
'}'
'}';
fastcgi_intercept_errors on;
server_names_hash_max_size 4096;
include /etc/nginx/conf.d/*.conf;
}
stream {
allow 111.11.11.11;
deny all;
proxy_timeout 1d;
proxy_connect_timeout 30;
upstream ssh-proxy {
server 192.168.1.1:22;
}
server {
listen 9888 ;
proxy_pass ssh-proxy;
}
}
主要是添加了 Stream 模块,注意 Stream 模块是同 http 模块同级的,而并非在 Http 模块之下。
allow是白名单的配置,只允许公司网络的网络出口可以进行ssh连接。
deny 是拒绝其他全部连接。
这里同样也可以做负载均衡的
bash
upstream ssh-proxy {
server 192.168.1.1:22;
server 192.168.1.1:23;
}
但我这个场景并没有什么意义,我就没有演示了,其他我暂时还木有想到很好的场景,如果大家有什么好的场景也可以说一说,讨论一下。
3.3、制作镜像
bash
docker build -t nginx-stream .
参数:-t 是用于指定镜像的名称,最后的小数点是表示Dockfile所在的当前目录,当文件名不再叫Dockerfile时,则需要添加 -f 来指定 Dockerfile 文件
3.4、运行容器
bash
docker run -d -p 9888:9888 --name nginx-stream nginx-stream
3.5、测试Stream模块
看看是否可以通过我们代理的端口来实现ssh连接
测试前记得要先打开防火墙,如果是云服务器,请记得开放端口,否则无法访问。
通过代理的端口去实现ssh连接
写到这里,我都不知道怎么去贴这个测试的图,看日志,日志中啥也没有,展示端口,也没有端口展示,没啥用。
后语
有问题的话,大家可以留言,或者私信,我都会在第一时间进行回复。
文中如有不对或不足之处,还请各位指正,非常感谢。
如果你持续对我,或者是对本系列相关的文章感兴趣,可以关注同名微信公众号《宁在春》,后续我会在第一时间将相关博客更新到公众号中。
非常感谢你的阅读,有所收获的话,还望不要吝啬赞和评论,不得不说,我想要获取一些坚持去写的动力,哈哈哈
读到最后,那就祝大家周末愉快啦~
春夏之际,与友踏青,我想应该是个非常不错的事情吧,大家可以试一试哦~
说的就是你,别卷了!!!