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

news2024/11/16 9:41:31

有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;
    }
}

运行结果:

注释代理,连接超时

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【送书活动】智能汽车、自动驾驶、车联网的发展趋势和关键技术

文章目录 前言01 《智能汽车》推荐语 02 《SoC底层软件低功耗系统设计与实现》推荐语 03 《SoC设计指南》推荐语 05 《智能汽车网络安全权威指南&#xff08;上册&#xff09;》推荐语 06 《智能汽车网络安全权威指南&#xff08;下册&#xff09;》推荐语 后记赠书活动 前言 …

普通二叉树和右倾斜二叉树--LeetCode 111题《Minimum Depth of Binary Tree》

本文将以解释计算二叉树的最小深度的思路为例&#xff0c;致力于用简洁易懂的语言详细描述普通二叉树和右倾斜二叉树在计算最小深度时的区别。通过跟随作者了解右倾斜二叉树的概念以及其最小深度计算过程&#xff0c;读者也将对左倾斜二叉树有更深入的了解。这将为解决LeetCode…

FreeRTOS学习——同步互斥

FreeRTOS学习——同步互斥 目录 FreeRTOS学习——同步互斥一、概念1.1 同步1.2 互斥 二、示例——有缺陷的同步三、示例——优化有缺陷的同步四、示例——有缺陷的互斥五、总结 一、概念 1.1 同步 在FreeRTOS中&#xff0c;同步是指任务之间按照某种规则进行协调和按序执行的…

HarmonyOS:使用MindSpore Lite引擎进行模型推理

场景介绍 MindSpore Lite 是一款 AI 引擎&#xff0c;它提供了面向不同硬件设备 AI 模型推理的功能&#xff0c;目前已经在图像分类、目标识别、人脸识别、文字识别等应用中广泛使用。 本文介绍使用 MindSpore Lite 推理引擎进行模型推理的通用开发流程。 基本概念 在进行开…

PDI/Kettle-9.2.0.0-R(对应jdk1.8)源码编译问题记录及源码结构简介

目录 &#x1f4da;第一章 前言&#x1f4d7;背景&#x1f4d7;目的&#x1f4d7;总体方向 &#x1f4da;第二章 代码结构初识基本结构&#x1f4d7;代码模块详情 ⁉️问题记录❓问题一&#xff1a;代码分支哪些是发布版本❗答&#xff1a;后缀-R的版本 ❓问题二&#xff1a;50…

AI智能配音助手微信小程序前后端源码支持多种声音场景选择

大家好今天给大家带来一款配音小程序 &#xff0c;这款小程序支持多种不同声音和场景的选择更人性化&#xff0c; 比如说支持各地区的方言,英文,童声呀等等、 另外也支持男声女声的选择,反正就是模板那些非常的多 当然啦音量,语调,语速那些都是可以DIY跳转的哟,所以说这一款小程…

使用PyTorch II的新特性加快LLM推理速度

Pytorch团队提出了一种纯粹通过PyTorch新特性在的自下而上的优化LLM方法&#xff0c;包括: Torch.compile: PyTorch模型的编译器 GPU量化:通过降低精度操作来加速模型 推测解码:使用一个小的“草稿”模型来加速llm来预测一个大的“目标”模型的输出 张量并行:通过在多个设备…

【专题】最小生成树(prim算法、kruscal算法)

目录 一、最小生成树二、Prim算法1. 算法思想2. 例题3. 性能分析 三、Kruscal算法1. 算法思想2. 例题3. 性能分析 一、最小生成树 生成树中边的权值&#xff08;代价&#xff09;之和最小的树。 二、Prim算法 1. 算法思想 设N(V,{E})是连通网&#xff0c;TE是N上最小生成树…

【IEEE】2区SCI,接收领域广,稳定检索47年!

重点 本期推荐 区块链是一种新兴技术&#xff0c;很多行业和领域都以创新方式采用了此技术&#xff0c;如能源、金融、媒体和娱乐以及零售等。此外&#xff0c;区块链作为一门新兴的交叉学科, 涉及密码学应用&#xff08;加密&#xff0c;隐私等&#xff09;&#xff0c; 分布式…

stm32与Freertos入门(二)移植FreeRTOS到STM32中

简介 注意&#xff1a;FreeRTOS并不是实时操作系统&#xff0c;而是分时复用的&#xff0c;只不过切换频率很快&#xff0c;感觉上是同时在工作。本次使用的单片机型号为STM32F103C8T6,通过CubeMX快速移植。 一、CubeMX快速移植 1、选择芯片 打开CubeMX软件&#xff0c;进行…

Diva配置——Communication Tests

关联文章:CANoe.Diva生成测试用例 Diva目录 一、CANoe.Diva简介二、Communication Tests配置一、CANoe.Diva简介 CANoe.DiVa 是一种 CANoe 选项,用于对 ECU 中的诊断软件实施进行自动化测试。 可以通过CANdelaStudio制作的CDD或ODX文件,经过Diva配置自动生成测试用例和测试脚…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于时空注意力卷积模型的超短期风电功率预测》

这个标题描述了一种用于超短期风电功率预测的模型&#xff0c;该模型基于时空注意力卷积模型。下面我会逐步解读这个标题的关键词和背景&#xff1a; 超短期风电功率预测&#xff1a;风电功率预测是指根据历史风速和其他相关数据&#xff0c;通过建立数学模型来预测未来特定时间…

Vue学习计划-Vue2--VueCLi(四)组件传值和自定义事件

1. 组件传值 组件化编码流程&#xff1a; 拆分静态组件&#xff1a;组件要按照功能点拆分&#xff0c;命名不要与html元素冲突实现动态组件&#xff1a;考虑好数据的存放位置&#xff0c;数据是一个组件在用&#xff0c;还是一些组件在用&#xff1a; 一个组件在用&#xff0c…

云演ctf 你能看到我吗?

1、看题目稍微尝试不好用&#xff0c;看到提示的文件访问也不好用。读取文件又好像拦截了啥。 读取hint.php文件payload ctfphp://filter/convert.base64-encode/resourcehihintnt.php2、解密后又看到一个文件 有需要绕过 ctfphp://filter/convert.base64-encode/resource..…

轻量封装WebGPU渲染系统示例<45>- 材质组装流水线(MaterialPipeline)灯光、阴影、雾(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/MaterialPipelineFog.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下&#xff1a; export class MaterialPipelineFog {pr…

C语言数组刷题-----数组填充

输入一个整数 V &#xff0c;输出一个长度为 10 的数组 N &#xff0c;数组中的第一个元素为 V &#xff0c;每个后续元素的值都为上一个元素的值的 2 倍。 例如&#xff0c;如果输入整数为 1 &#xff0c;则数组为&#xff1a;1,2,4,8… 输入格式 输入一个整数 V 。输出格…

cmake多模块架构, DLL依赖编译

整体结构&#xff1a; 最外层的cmakelist CMakeLists.txt project(cmakeMulPackage) cmake_minimum_required(VERSION 3.17) set(CMAKE_CXX_STANDARD 11)#设置环境相关 message("set env.cmake") message("CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}") …

TG-5510cb: txo高稳定性+105℃高温

TG-5510CB是一款高稳定性TCXO&#xff0c;可提供CMOS或限幅正弦输出&#xff0c;5G基站和边缘计算的额定温度为85C&#xff0c;需要室外安装、小型化和无风扇运行。与其他TCXO相比&#xff0c;实验室提供了许多改进&#xff0c;如低温度斜率和相位噪声。符合GR-1244-CORE地层3和…

详细教程 - 从零开发 Vue 鸿蒙harmonyOS应用 第一节

关于使用Vue开发鸿蒙应用的教程,我这篇之前的博客还不够完整和详细。那么这次我会尝试写一个更加完整和逐步的指南,从环境准备,到目录结构,再到关键代码讲解,以及调试和发布等,希望可以让大家详实地掌握这个过程。 一、准备工作 下载安装 DevEco Studio 下载地址&#xff1a;…

AD20-Excel创建IC类元件库

目录 准备模板AD操作 准备模板 AD操作 结果生成如下&#xff1a; over&#xff01;&#xff01;&#xff01;