http正向代理测试,nginx反向代理中转正向代理服务器

有3台服务器如下:
192.168.111.201(反向代理到正向代理服务器)
192.168.111.202(正向代理服务器)
192.168.111.203(目标WEB系统)

防火墙网络策略如图所示:
1、192.168.111.200 只能访问 192.168.111.201 的 8081端口。
2、192.168.111.201 只能访问 192.168.111.202 的 8082端口。
2、192.168.111.202 只能访问 192.168.111.203 的 8083/8084/8085端口。

目标:
本地192.168.111.200 发送http请求 http://192.168.111.203:8083/web 能够返回结果。

一、网络策略

1、192.168.111.201 开放8081端口

#清空防火墙规则
mv public.xml public.xml.bak
systemctl restart firewalld

#开启端口
firewall-cmd --permanent --add-port=8081/tcp

#重新加载生效
firewall-cmd --reload

#查询有哪些端口是开启的
firewall-cmd --list-port

2、192.168.111.202 只对 192.168.111.201 开放8082端口

#清空防火墙规则
mv public.xml public.xml.bak
systemctl restart firewalld

#只允许192.168.111.201访问8082端口,注意这里有两个port不是写错了
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.111.201 port port=8082 protocol=tcp accept'

#重新加载生效
firewall-cmd --reload

#查看规则
firewall-cmd --list-rich-rules

#删除规则
firewall-cmd --permanent --remove-rich-rule='<RULE>'

3、192.168.111.203 只对 192.168.111.202 开放8083端口 

#清空防火墙规则
mv public.xml public.xml.bak
systemctl restart firewalld

#只允许192.168.111.202访问8083端口,注意这里有两个port不是写错了
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.111.202 port port=8083 protocol=tcp accept'

#重新加载生效
firewall-cmd --reload

#查看规则
firewall-cmd --list-rich-rules

#删除规则
firewall-cmd --permanent --remove-rich-rule='<RULE>'

测试网络策略

#安装telnet客户端
yum -y install telnet.*


telnet 192.168.111.202 8082 只有192.168.111.201通
telnet 192.168.111.203 8083 只有192.168.111.202通

 

二、192.168.111.201

安装 nginx

# 安装四个依赖
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
# 有些系统还需要多安装几个依赖
# yum -y install make gcc-c++ libtool
yum -y install wget
wget http://nginx.org/download/nginx-1.13.7.tar.gz
tar -zxvf nginx-1.13.7.tar.gz
cd nginx-1.13.7
./configure --prefix=/usr/local/nginx --with-stream
make && make install

修改配置 vi /usr/local/nginx/conf/nginx.conf,反向代理到 192.168.111.202

​
stream {
    server {
        listen 8081;
        proxy_pass 192.168.111.202:8082;
    }
}

​

启动nginx

cd /usr/local/nginx/sbin/
./nginx

三、192.168.111.202

 部署正向代理服务器

package com.study.proxy;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 正向代理
 * @Date: 2023/11/20 14:49
 */
public class Proxy {
    private static Logger logger = LoggerFactory.getLogger(Proxy.class);

    public static void main(String[] args) throws Exception {
        startProxyServer();
    }


    // 启动代理服务器
    public static void startProxyServer() {
        new Thread(new ProxyServer()).start();
    }

    // 代理服务器
    static class ProxyServer implements Runnable {
        @Override
        public void run() {
            try {
                // 监听指定的端口
                int port = 8082; //一般使用49152到65535之间的端口
                ServerSocket server = new ServerSocket(port);
                // 当一个ServerSocket关闭并释放其绑定的端口后,操作系统通常会在几分钟内不允许其他Socket再次绑定到该端口。
                // true:操作系统将允许其他Socket立即绑定到刚刚被释放的端口。
                server.setReuseAddress(true);
                // 使用线程池,防止过多线程耗尽资源
                ExecutorService threadPool = Executors.newFixedThreadPool(50);
                while (true) {
                    Socket socket = server.accept(); //会一直阻塞,直到有客户端连接进来
                    // new Thread 只是创建一个类的对象实例而已。而真正创建线程的是start()方法。
                    // 这里并没有直接调用start()方法,所以并没创建新线程,而是交给线程池去执行。
                    threadPool.submit(new ProxyClient(socket));
                }
            } catch (Exception e) {
                logger.error("ProxyServer", e.getMessage(), e);
            }
        }
    }

    // 代理客户端
    static class ProxyClient implements Runnable {
        private final Socket proxySocket;//代理Socket
        private Socket targetSocket = null;//目标Socket

        public ProxyClient(Socket socket) {
            this.proxySocket = socket;
        }

        @Override
        public void run() {
            try {
                //客户端请求的报文
                InputStream req = proxySocket.getInputStream();
                int read;
                int contentLength = 0;//body长度
                String method = null;//请求方法
                String url = null;//请求地址
                String protocol = null;//请求协议
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ByteArrayOutputStream reqBack = new ByteArrayOutputStream();
                //解析,提取请求报文
                while ((read = req.read()) != -1) {
                    os.write(read);
                    reqBack.write(read);
                    if (read == '\n') {
                        //CONNECT www.xx.com:443/xx/yy HTTP/1.1
                        String line = os.toString("UTF-8");
                        os.reset();//重置,以便再次使用
                        if ("\r\n".equals(line)) {
                            //空行,请求头结束标志
                            break;
                        }
                        StringTokenizer stringTokenizer = new StringTokenizer(line, " ");
                        if (method == null) {
                            //八种请求方法:GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT 方法
                            method = stringTokenizer.nextToken().toLowerCase();//connect
                            url = stringTokenizer.nextToken();//www.xx.com:443/xx/yy
                            protocol = stringTokenizer.nextToken().trim();//HTTP/1.1
                        } else {
                            String key = stringTokenizer.nextToken().toLowerCase();
                            if ("content-length:".equals(key)) {
                                String value = stringTokenizer.nextToken().trim();
                                contentLength = Integer.parseInt(value);
                            }
                        }
                    }
                }
                if (contentLength > 0) {
                    for (int i = 0; i < contentLength; i++) {
                        reqBack.write(req.read());
                    }
                }
                //完整请求报文
                // String request = reqBack.toString("UTF-8");
                // System.out.println("请求报文开始");
                // System.out.print(request);
                // System.out.println("\r\n请求报文结束");


                //拼接完整url
                if (url != null && !url.startsWith("http")) {
                    url = method.equals("connect") ? "https://" + url : "http://" + url;
                }
                URL u = new URL(url);
                //目标ip
                String targetHost = u.getHost();
                //目标端口
                int targetPort = u.getPort();
                if (targetPort == -1) {
                    targetPort = 80;
                }

                //目标Socket
                targetSocket = new Socket(targetHost, targetPort);

                if ("connect".equals(method)) {//https
                    //HTTP/1.1 200 Connection established
                    //报文直接发送给代理Socket
                    OutputStream outputStream = proxySocket.getOutputStream();
                    outputStream.write((protocol + " 200 Connection established\r\n").getBytes(StandardCharsets.UTF_8));
                    outputStream.write("Proxy-agent: ProxyServer/1.0\r\n".getBytes(StandardCharsets.UTF_8));
                    outputStream.write("\r\n".getBytes(StandardCharsets.UTF_8));
                    outputStream.flush();

                    //前者转发给后者,代理Socket转发给目标Socket
                    Thread proxy2target = new Thread(new ForwardData(proxySocket, targetSocket));
                    proxy2target.start();

                    //前者转发给后者,目标Socket转发给代理Socket
                    Thread target2proxy = new Thread(new ForwardData(targetSocket, proxySocket));
                    target2proxy.start();

                    proxy2target.join();

                } else {//http
                    //请求报文转发给目标Socket
                    OutputStream outputStream = targetSocket.getOutputStream();
                    outputStream.write(reqBack.toByteArray());
                    outputStream.flush();

                    //前者转发给后者,目标Socket转发给代理Socket
                    Thread thread = new Thread(new ForwardData(targetSocket, proxySocket));
                    thread.start();
                    thread.join();
                }
            } catch (Exception e) {
                logger.error("ProxyClient", e.getMessage(), e);
            } finally {
                try {
                    if (targetSocket != null) {
                        targetSocket.close();
                    }
                } catch (IOException e) {
                    logger.error("ProxyClient", e.getMessage(), e);
                }
                try {
                    if (proxySocket != null) {
                        proxySocket.close();
                    }
                } catch (IOException e) {
                    logger.error("ProxyClient", e.getMessage(), e);
                }
            }
            // logger.error("ProxyClient", "结束");
        }

        // 转发数据
        static class ForwardData implements Runnable {
            private final Socket inputSocket;
            private final Socket outputSocket;

            public ForwardData(Socket inputSocket, Socket outputSocket) {
                this.inputSocket = inputSocket;
                this.outputSocket = outputSocket;
            }

            @Override
            public void run() {
                try {
                    InputStream inputStream = inputSocket.getInputStream();
                    OutputStream outputStream = outputSocket.getOutputStream();
                    int read;
                    while ((read = inputStream.read()) != -1) {
                        outputStream.write(read);
                    }
                } catch (Exception e) {
                    // logger.error("ForwardData", inputSocket + e.getMessage());
                }
            }
        }

    }
}

四、192.168.111.203

部署目标web服务

@RestController
public class WebController {

    @GetMapping("/web")
    public String web() {
        return "ok";
    }
}

五、本地测试

package com.study.client;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 测试
 */
public class Test {
    public static void main(String[] args) {
        // 正向代理服务器
        System.setProperty("http.proxyHost", "192.168.111.201");
        System.setProperty("http.proxyPort", "8081");
        // 目标地址
        String url = "http://192.168.111.203:8083/web";
        String sendGet = sendGet(url);
        System.out.println(sendGet);
    }

    public static String sendGet(String url) {
        HttpURLConnection con = null;
        InputStream is = null;
        try {
            con = (HttpURLConnection) new URL(url).openConnection();
            is = con.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = is.read(buf)) != -1) {
                baos.write(buf, 0, len);
                baos.flush();
            }
            return baos.toString("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (con != null) {
                    con.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

运行结果:

注释代理,连接超时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/249483.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

主宰无双H5:WIN学习手工服务端通用视频教程及GM授权物品后台,支持三网H5玩法介绍

标题&#xff1a;主宰无双H5&#xff08;游戏源码&#xff09;&#xff1a;WIN学习手工服务端通用视频教程及GM授权物品后台&#xff0c;支持三网H5玩法的百科 一、引言 随着互联网的快速发展&#xff0c;H5游戏逐渐成为人们休闲娱乐的重要方式。主宰无双H5游戏源码作为一款深…

深入理解LightGBM

1. LightGBM简介 GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型&#xff0c;其主要思想是利用弱分类器&#xff08;决策树&#xff09;迭代训练以得到最优模型&#xff0c;该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛&#…

初识Redis缓存,一文掌握Redis重要知识文集。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

QWebEngineView 透明色 设置白屏闪烁的问题 已解决

在项目开发中。由于qt5.15 升级到qt6.5 不知道因为什么&#xff0c;QWebEngineView 加载出现白屏&#xff0c; 网上大神给的方案 五花八门&#xff0c;没有一个解决问题。 代码 旧代码QWebEngineView* pWebEngineView new QWebEngineView();//pWebEngineView->page()->…

HTML+CSS高频面试题

面试题目录 前言1.讲一下盒模型&#xff0c;普通盒模型和怪异盒模型有什么区别2.CSS如何实现居中3.讲一下flex弹性盒布局4.CSS常见的选择器有哪些&#xff1f;优先级5.长度单位px 、em、rem的区别6.position属性的值有哪些7.display属性的值有哪些&#xff0c;分别有什么作用8.…

ChatGPT在指尖跳舞: open-interpreter实现本地数据采集、处理一条龙

原文&#xff1a;ChatGPT在指尖跳舞: open-interpreter实现本地数据采集、处理一条龙 - 知乎 目录 收起 Part1 前言 Part2 Open - Interpreter 简介 Part3 安装与运行 Part4 工作场景 1获取网页内容 2 pdf 文件批量转换 3 excel 文件合并 Part5总结 参考资料 往期推…

字符设备驱动模块的编译

一. 简介 本文继上一篇文章的学习&#xff0c;上一篇文章学习了字符设备驱动框架的初步编写。文章地址如下&#xff1a; 字符设备驱动框架的编写-CSDN博客 本文对上一篇编写的驱动模块初步框架进行编译。 二. 字符设备驱动模块的编译 上一篇文章&#xff0c;编写了字符设备…

多分类预测 | MATLAB实现CNN-LSTM-Attention多输入分类预测

分类预测 | MATLAB实现CNN-LSTM-Attention多输入分类预测 分类效果 需要源码和数据的私信&#xff08;微微有偿取哦&#xff09;

swing快速入门(十二)

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1.Box容器和BroadLayout布局管理器的结合用法 2.textArea&#xff08;多行文本域&#xff09; 3.Choice&#xff08;下拉选择栏&#xff09; 4. CheckboxGroup&#xff08;多项单选选择框&#xff09; 5. Checkbox&…

爬虫chrome浏览器抓包说明

chrome浏览器抓包说明 目标&#xff1a;掌握chrome在爬虫中的使用 1. 新建隐身窗口&#xff08;无痕窗口&#xff09; 作用&#xff1a;在打开无痕窗口的时候&#xff0c;第一次请求某个网站是没有携带cookie的&#xff0c;和代码请求一个网站一样&#xff0c;这样就能够尽可…

网络服务IP属地发生变化的原因有哪些?

近期&#xff0c;许多用户发现自己的网络服务IP属地发生了变化。原本固定的IP地址不再是静态的&#xff0c;而是发生了变动。这一现象引起了广大用户的关注和疑惑&#xff0c;对网络服务的使用和信息安全产生了影响。为了解决用户的疑虑&#xff0c;我们对此现象进行了深入探究…

.NET 8的正式发布,对Telerik开发工具意味着什么?

微软日前正式发布了.NET 8稳定版&#xff0c;这是一个长期支持(LTS)的版本&#xff0c;它可以使Android、Windows和macOS跨平台应用的开发过程高效流畅&#xff0c;同样的目标也驱使着Telerik UI不断进步和发展&#xff01; Telerik DevCraft包含一个完整的产品栈来构建您下一个…

现代雷达车载应用——第2章 汽车雷达系统原理 2.6节 雷达设计考虑

经典著作&#xff0c;值得一读&#xff0c;英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.6 雷达设计考虑 上述部分给出了汽车雷达基本原理的简要概述。在雷达系统的设计中&#xff0c;有几个方面是必不可少的&#xff0c;它们决定了雷达系…

真正可行的vue3迁移到nuxt3方法(本人亲测,完全避坑)

终于到了总结经验的时候了&#xff0c;这绝对是全网唯一、完全真正可行的干货。 在我看来&#xff0c;知识就是要拿来分享的&#xff0c;分享给他人也是在提高自己。我绝对不会搞什么订阅或者vip专栏来搞钱坑害各位&#xff0c; 因为我在csdn写文章最主要的目的是为了记录和总…

接口测试 — 4.Requests库GET、Post请求

Requests库GET请求是使用HTTP协议中的GET请求方式对目标网站发起请求。 &#xff08;不带参数的GET请求请看上一篇文章的练习&#xff09; 1、Requests库待参数的GET请求 使用Get方法带参数请求时&#xff0c;是params参数字典&#xff0c;而不是data参数字典。data参数字典…

从零开始:前端架构师的基础建设和架构设计之路

文章目录 一、引言二、前端架构师的职责三、基础建设四、架构设计思想五、总结《前端架构师&#xff1a;基础建设与架构设计思想》编辑推荐内容简介作者简介目录获取方式 一、引言 在现代软件开发中&#xff0c;前端开发已经成为了一个不可或缺的部分。随着互联网的普及和移动…

Redis 过期删除策略、内存回收策略、单线程理解

不知从何开始Redis的内存淘汰策略也开始被人问及&#xff0c;卷&#xff01;真的是太卷了。难不成要我们去阅读Redis源码吗&#xff0c;其实问题的答案&#xff0c;在Redis中的配置文件中全有&#xff0c;不需要你阅读源码、这个东西就是个老八股&#xff0c;估计问这个东西是想…

深度探索Linux操作系统 —— 构建根文件系统

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 深度探索Linux操作系统 —— 从内核空间到用户空间 深度探索Linux操作系统 —— 构建根文件系统…

金融众筹系统源码:适合创业孵化机构 附带完整的搭建教程

互联网技术的发展&#xff0c;金融众筹作为一种新型的融资方式&#xff0c;逐渐成为创业孵化机构的重要手段。为了满足这一需求&#xff0c;金融众筹系统源码就由此而生&#xff0c;并附带了完整的搭建教程。 以下是部分代码示例&#xff1a; 系统特色功能一览&#xff1a; 1.…

发现隐藏的 Web 应用程序漏洞

随着 Web 2.0 的扩展&#xff0c;近年来社交媒体平台、电子商务网站和电子邮件客户端充斥着互联网空间&#xff0c;Web 应用程序已变得无处不在。 国际知名网络安全专家、东方联盟创始人郭盛华透露&#xff1a;‘应用程序消耗和存储更加敏感和全面的数据&#xff0c;它们成为对…