Nginx做HTTP代理和邮件服务器代理

一、背景

最近公司在做网络安全整改,对大数据环境的网络安全要求更高,要求所有的大数据环境的机器不能访问外网,但是可以访问公司的非大数据环境的其他服务器。我们组有四台单独的机器在大数据环境中,相关的python脚本都部署在这4台机器上,这些python脚本都是做大数据相关分析的,同时很多都有访问外网的需求,比如访问天气api查询历史天气、访问百度距离api查询、根据统计数据定时发邮件等,这些都是访问外网的。

大数据环境的机器不能访问外网,但是可以访问公司非大数据环境的机器,非大数据环境的机器可以访问外网。在考虑整改带来的代码入侵性和公司网络现状的情况下,准备申请一台在公司非大数据环境的机器做外网出口的正向代理,将所有的外网访问地址统一转到这台机器上,然后由这一台机器统一访问外网;这样及可以满足安全需求,也可以较少的修改代码,只需要替换现有外网地址对应的ip和端口即可。

二、整改过程

2.1.现状分析

统计现在四台机器的外网访问情况。发现主要有外网访问:一是调用外部的天气API和百度距离API,另一种是定时发邮件到相关同事的邮箱中;所以需要做两类代理:http代理、邮件服务器代理。

2.2.申请机器,搭建Nginx

需要申请一台不在大数据环境但是在公司网络环境的机器,并且大数据机器可以访问这台机器,同时这台机器可以访问外网。(目前申请一台机器,未考虑高可用)。

申请的机器地址:101.147.192.179。 作用:安装nginx,做为代理,后续不管是访问http外部接口还是发邮件,都使用这个ip。

公司真实的邮件服务器地址:http://mail.xxxxxx.cn

搭建nginx:

[ops@dis-algo data]$ [ops@dis-algo data]$ mkdir nginx [ops@dis-algo data]$ [ops@dis-algo data]$ cd nginx/ [ops@dis-algo nginx]$ # 下载nginx [ops@dis-algo nginx]$ wget [ops@dis-algo nginx]$ ls nginx-1.20.1.tar.gz [ops@dis-algo nginx]$ # 解压 [ops@dis-algo nginx]$ tar -zxvf nginx-1.20.1.tar.gz [ops@dis-algo nginx]$ ll total 1040 drr-xr-x 8 ops ops 158 May 25 20:35 nginx-1.20.1 -rw-rw-r-- 1 ops ops May 25 23:34 nginx-1.20.1.tar.gz [ops@dis-algo nginx]$ [ops@dis-algo nginx]$ cd nginx-1.20.1/ [ops@dis-algo nginx-1.20.1]$ ls autoCHANGESCHANGES.ruconfconfigurecontribhtmlLICENSEmanREADMEsrc [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ # 配置。由于是使用stream方式代理邮件服务器,所以需要--with-stream模块,不要--with-mail模块 # 同时需要http代理相关的模块 # 安装的路径在当前目录的上一级 --prefix=.. 直接在当前目录安装由于文件冲突会报错 [ops@dis-algo nginx-1.20.1]$ ./configure --prefix=.. --with-http_stub_status_module --with-http_ssl_module --with-stream [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ # 编译、安装 [ops@dis-algo nginx-1.20.1]$ make [ops@dis-algo nginx-1.20.1]$ make install [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ ls autoCHANGESCHANGES.ruconfconfigurecontribhtmlLICENSEMakefilemanobjsREADMEsrc [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ [ops@dis-algo nginx-1.20.1]$ # 回到上一级的安装目录 [ops@dis-algo nginx-1.20.1]$ cd .. [ops@dis-algo nginx]$ ls confhtmllogsnginx-1.20.1nginx-1.20.1.tar.gzsbin [ops@dis-algo nginx]$ [ops@dis-algo nginx]$

2.3.配置http代理和邮件代理

​ [ops@dis-algo nginx]$ [ops@dis-algo nginx]$ cd conf/ # 找到配置文件 nginx.conf [ops@dis-algo conf]$ ls fastcgi.conffastcgi_paramskoi-utfmime.typesnginx.confscgi_paramsuwsgi_paramswin-utf fastcgi.conf.defaultfastcgi_params.defaultkoi-winmime.types.defaultnginx.conf.defaultscgi_params.defaultuwsgi_params.default [ops@dis-algo conf]$ [ops@dis-algo conf]$ # 根据具体情况修改配置文件 完成http代理和邮件代理的配置 [ops@dis-algo conf]$ vim nginx.conf [ops@dis-algo conf]$ [ops@dis-algo conf]$ cat nginx.conf worker_processes8; error_log/data/nginx/logs/error.log; pid/data/nginx/logs/nginx.pid; ​ events { worker_connections1024; } ​ # http代理 http { include mime.types; default_typeapplication/octet-stream; sendfileon; keepalive_timeout65; ​ ​ log_formatmain$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"; access_log/data/nginx/logs/access.logmain; ​ # DNS服务器 resolver 8.8.8.8; ​ server { # 后续外部http请求都使用101.147.192.179:18080访问 server_name101.147.192.179; listen 18080; keepalive_requests 120; ​ # 对每个http接口做代理 location ^~ /caiyunapp/ { proxy_pass; } ​ # get传参使用$request_uri location = /routematrix/v2/riding { proxy_passhttp://api.map.baidu.com$request_uri; } ​ location ^~ /tianqihoubao { proxy_pass; } ​ location ^~ /weather { proxy_pass; } } } ​ # 邮件服务器代理 需要使用--with-stream模块 stream { server { listen 25; # 这里必须使用25 其他的端口号我没有测通;使用25端口要求启动使用root权限 proxy_pass mail.xxxxxx.cn:25; # 原来的公司邮件服务器 } } ​ [ops@dis-algo conf]$ # 测试配置文件是否正确 [ops@dis-algo conf]$ ../sbin/nginx -t nginx: the configuration file ../conf/nginx.conf syntax is ok nginx: configuration file ../conf/nginx.conf test is successful [ops@dis-algo conf]$ # 启动 报错 # 需要执行nginx -c nginx.conf命令指定配置文件 [ops@dis-algo conf]$ ../sbin/nginx-s reload nginx: [error] invalid PID number "" in "/data/nginx/logs/nginx.pid" [ops@dis-algo conf]$ # 指定配置文件。 要求使用sudo,因为邮件代理使用的是25端口,这个端口要求root [ops@dis-algo conf]$ sudo ../sbin/nginx-c /data/nginx/conf/nginx.conf [ops@dis-algo conf]$ # 切换root用户前,先关闭nginx [ops@dis-algo conf]$ [ops@dis-algo conf]$ ../sbin/nginx-s stop [ops@dis-algo conf]$ # 以root用户重启 要求先以root用户身份指定配置文件(sudo nginx -c ) [ops@dis-algo conf]$ sudo ../sbin/nginx -s reload [ops@dis-algo conf]$ # 查看是否重启成功 [ops@dis-algo conf]$ netstat -nltp | grep 25 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp00 0.0.0.0:250.0.0.0:* LISTEN- [ops@dis-algo conf]$ ​

2.4.测试

在大数据环境的四台机器上测试。

2.4.1.Http代理测试

1.测试api.caiyunapp.com 原来的地址: curl v2.5/YRVvqVfC3j0K794p/119.,26./realtime.json 代理的地址: curl :18080/caiyunapp/v2.5/YRVvqVfC3j0K794p/119.,26./realtime.json ​ 2.测试api.map.baidu.com 原来的地址: curl ?output=json\&riding_type=1\&origins=30.,104.\&destinations=30.,104.\&ak=5xYpGVj7A9WqnHERyB9U4QtM6uRTO75T 代理的地址: curl :18080/routematrix/v2/riding?output=json\&riding_type=1\&origins=30.,104.\&destinations=30.,104.\&ak=5xYpGVj7A9WqnHERyB9U4QtM6uRTO75T ​ 3.测试www.tianqihoubao.com 原来的地址: curllishi/wuxi/month/.html 代理的地址: curl:18080/tianqihoubao/lishi/wuxi/month/.html ​ 4.测试www.weather.com.cn 原来的地址: curl weather15d/.shtml 代理的地址: curl :18080/weather/weather15d/.shtml ​

2.4.2.邮件代理测试

1.引入jar包 <!--发邮件--> <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.5.6</version> </dependency> 2.java测试 package com.wuxiaolong; ​ import javax.mail.*; import javax.mail.internet.*; import java.util.Properties; ​ public class TestEmail { ​ private final static String TIMEOUT_MS = "20000"; ​ public static void main(String[] args)throws Exception{ // 这是公司原来的邮件服务器 代理之前使用这个 // String host = "mail.xxxxxx.cn"; ​ // 这是代理服务器(nginx) 代理之后使用这个 String host = "101.147.192.179"; ​ String port = "25";// SMTP邮件服务器默认端口 ​ // 公司的邮箱发邮件 String user = "[email protected]"; String password = "XXXXXX"; ​ // 163邮箱收邮件 String recipients = "[email protected]"; ​ String subject = "邮件发送测试"; String content = "邮件正文:<br>你好 proxy!"; ​ ​ Properties props = new Properties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", port); props.put("mail.smtp.host", host); props.put("mail.smtp.timeout", TIMEOUT_MS); ​ ​ Authenticator auth = new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user, password); } }; Session session = Session.getInstance(props, auth); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(user)); msg.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients)); ​ msg.setSubject(subject); // 向multipart对象中添加邮件的各个部分内容,包括文本内容和附件 Multipart multipart = new MimeMultipart(); // 添加邮件正文 BodyPart contentPart = new MimeBodyPart(); contentPart.setContent(content, "text/html;charset=UTF-8"); multipart.addBodyPart(contentPart); ​ // 将multipart对象放到message中 msg.setContent(multipart); // 保存邮件 msg.saveChanges(); Transport.send(msg, msg.getAllRecipients()); } ​ } ​

测试结果:

2.5.修改代码

相关的python代码按照上面2.4的测试的代理地址进行修改。

2.6.后续注意事项

后续这四台机器上有新的外网地址访问,需要提前加入到这台代理机器上。