Java实现Http代理服务器&通过http代理进行内网安装yum软件

  • 1.Http代理服务器简介
  • 2.Http代理服务器Java实现
    • 2.1 Java源码
    • 2.2 代码分析说明
  • 3.通过http代理进行内网安装yum软件
    • 3.1 步骤2实现的代理服务器启动
    • 3.2通过securecrt进行远程内网服务器的连接
    • 3.3 进行export配置通过http代理访问
    • 3.4 通过代理进行yum软件的安装
  • 4. 总结

本文通过Java进行http代理服务器实现,并在这个Java版http代理服务器的基础上,再描述如何通过http代理进行内网系统的yum软件安装

1.Http代理服务器简介

HTTP代理服务器是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。

HTTP代理:http请求经过代理服务器,代理服务器只要负责转发相应的http响应体就可以

HTTPS代理:https请求经过代理服务器,会发送一个CONNECT报文,用于和代理服务器建立隧道,如果代理服务器返回HTTP 200,则建立成功,后续代理服务器只要负责转发数据。

2.Http代理服务器Java实现

常见的http代理服务器实现有ccproxy,haproxy,nginx等,这里通过Java实现简单的http代理服务器

通过Java进行http代理服务器实例,主要是解析http协议头里面的消息,解析出此请求是http还是https请求,如果是http请求,就解析出真实的请求的host,然后进行数据转发,如果是https请求,就进行CONNECT的解析,然后返回给客户端,再继续进行数据的转发。

2.1 Java源码

整个实现代码,采用一个Java类实现如下,将内容复制到你的idea或eclipse中编绎就可,无任何jar包依赖。

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Base64;
import java.util.Date;/*** http代理服务器,隧道模式* @author liujh*/
public class ProxyHttpsServer {private final int bufferSize = 8092;private int defaultPort = 1080; //默认端口private int localPort ;private ServerSocket localServerSocket;private boolean socksNeekLogin = true;//是否需要登录private String username = "admin";private String password = "admin123";public static void main(String[] args) {Integer port = args.length == 1 ? Integer.parseInt(args[0]) : null;new ProxyHttpsServer(port).startService();}public ProxyHttpsServer(Integer port){this.localPort = port == null ? defaultPort : port;}public void startService() {try {//开启一个ServerSocket服务器,监听请求的到来.localServerSocket = new ServerSocket(localPort);log("httpproxy server started , listen on " +localServerSocket.getInetAddress().getHostAddress()+":"+ localPort );// 一直监听,接收到新连接,则开启新线程去处理while (true) {Socket localSocket = localServerSocket.accept();new SocketThread(localSocket).start();}} catch (IOException e) {e.printStackTrace();}}//格式化打印方法,用来打印信息private final void log(Object message, Object... args) {Date dat = new Date();String msg = String.format("%1$tF %1$tT %2$-5s %3$s%n", dat, Thread.currentThread().getId(), String.format(message.toString(),args));System.out.print(msg);}/*** IO操作中共同的关闭方法* @param socket*/protected final void closeIo(Socket closeable) {if (null != closeable) {try {closeable.close();} catch (IOException e) {}}}/*** IO操作中共同的关闭方法* @param socket*/protected final void closeIo(Closeable closeable) {if (null != closeable) {try {closeable.close();} catch (IOException e) {}}}private class SocketThread extends Thread {private Socket localSocket;private Socket remoteSocket;private InputStream lin;private InputStream rin;private OutputStream lout;private OutputStream rout;public SocketThread(Socket socket) {this.localSocket = socket;}public void run() {//获取远程socket的地址,然后进行打印String addr = localSocket.getRemoteSocketAddress().toString();log("process one socket : %s", addr);try {lin = localSocket.getInputStream();lout = localSocket.getOutputStream();StringBuilder headStr = new StringBuilder();BufferedReader br = new BufferedReader(new InputStreamReader(lin));//读取HTTP请求头,并拿到HOST请求头和methodString line;String host = "";String proxy_Authorization = "";while ((line = br.readLine()) != null) {//打印http协议头log(line);headStr.append(line + "\r\n");if (line.length() == 0) {break;} else {String[] temp = line.split(" ");if (temp[0].contains("Host")) {host = temp[1];}//如果配置了需要登陆,就解析消息头里面的Proxy-Authorization字段,认证的账号和密码信息是通过base64加密传过来的。if(socksNeekLogin && temp[0].contains("Proxy-Authorization")){//获取认证信息proxy_Authorization = temp[2];}}}String type = headStr.substring(0, headStr.indexOf(" "));//根据host头解析出目标服务器的host和portString[] hostTemp = host.split(":");host = hostTemp[0];int port = 80;if (hostTemp.length > 1) {port = Integer.valueOf(hostTemp[1]);}boolean isLogin = false;//如果需要登录,校验登录是否通过if(socksNeekLogin){//通过username和password进行base64加密得到一个串,然后和请求里面传过来的Proxy-Authorization比较,一致的话就认证成功。String authenticationEncoding = Base64.getEncoder().encodeToString(new String(username + ":" + password).getBytes());if(proxy_Authorization.equals(authenticationEncoding)){isLogin = true;//登录通过//log("login success, basic: %s", proxy_Authorization);}else {log("httpproxy server need login,but login failed .");}}//不需要登录或已被校验登录成功,才进入代理,否则直接程序结束,关闭连接if(!socksNeekLogin || isLogin){//连接到目标服务器remoteSocket = new Socket(host, port);//进行远程连接rin = remoteSocket.getInputStream();rout = remoteSocket.getOutputStream();//根据HTTP method来判断是https还是http请求if ("CONNECT".equalsIgnoreCase(type)) {//https先建立隧道lout.write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes());lout.flush();}else {//http直接将请求头转发rout.write(headStr.toString().getBytes());rout.flush();}new ReadThread().start();//设置超时,超过时间未收到客户端请求,关闭资源//remoteSocket.setSoTimeout(10000);//写数据,负责读取客户端发送过来的数据,转发给远程byte[] data = new byte[bufferSize];int len = 0;while((len = lin.read(data)) > 0){if(len == bufferSize) {//读到了缓存大小一致的数据,不需要拷贝,直接使用rout.write(data);rout.flush();}else {//读到了比缓存大小的数据,需要拷贝到新数组然后再使用byte[] dest = new byte[len];System.arraycopy(data, 0, dest, 0, len);rout.write(dest);rout.flush();}}}} catch (Exception e) {log("exception : %s %s", e.getClass(), e.getLocalizedMessage());//e.printStackTrace();} finally {log("close socket, system cleanning ...  %s ", addr);closeIo(lin);closeIo(rin);closeIo(lout);closeIo(rout);closeIo(localSocket);closeIo(remoteSocket);}}//读数据线程负责读取远程数据后回写到客户端class ReadThread extends Thread {@Overridepublic void run() {try {byte[] data = new byte[bufferSize];int len = 0;while((len = rin.read(data)) > 0){if(len == bufferSize) {//读到了缓存大小一致的数据,不需要拷贝,直接使用lout.write(data);lout.flush();}else {//读到了比缓存大小的数据,需要拷贝到新数组然后再使用byte[] dest = new byte[len];System.arraycopy(data, 0, dest, 0, len);lout.write(dest);lout.flush();}}} catch (IOException e) {//log(remoteSocket.getLocalAddress() + ":"+ remoteSocket.getPort() + " remoteSocket InputStream disconnected.");} finally {}}}}}

2.2 代码分析说明

  1. ##可支持http代理,认证或不认证功能通过socksNeekLogin参数来支持,如果socksNeekLogin设置为true,说明需要进行认证,并相应的username和password为认证的账号和密码。
    private boolean socksNeekLogin = true;//是否需要登录private String username = "admin";private String password = "admin123";
  1. ##首先定义一个ServerSocket服务器,监听端口1080,端口可以通过命令行参数进行修改。
         //开启一个ServerSocket服务器,监听请求的到来.localServerSocket = new ServerSocket(localPort);log("httpproxy server started , listen on " +localServerSocket.getInetAddress().getHostAddress()+":"+ localPort );
  1. ##阻塞循环等待请求进来,收到一个请求后,开启一个线程进行处理
            // 一直监听,接收到新连接,则开启新线程去处理while (true) {Socket localSocket = localServerSocket.accept();new SocketThread(localSocket).start();}
  1. ##在新开启的线程中进行主要逻辑的处理。先进行简单的打印远程的连接
         //获取远程socket的地址,然后进行打印String addr = localSocket.getRemoteSocketAddress().toString();log("process one socket : %s", addr);
  1. ##接着通过BufferedReader包装好inputstream流,然后一行一行的读。如果某一行含有Host,就解析出真实目标服务器的ip和端口
  2. ##如何设置了需要登陆,就解析消息头中的Proxy-Authorization字段,然后进行账号密码判断是否一致,决定是否认证成功
//如果配置了需要登陆,就解析消息头里面的Proxy-Authorization字段,认证的账号和密码信息是通过base64加密传过来的。
if(socksNeekLogin && temp[0].contains("Proxy-Authorization")){//获取认证信息proxy_Authorization = temp[2];
}
boolean isLogin = false;
//如果需要登录,校验登录是否通过
if(socksNeekLogin){//通过username和password进行base64加密得到一个串,然后和请求里面传过来的Proxy-Authorization比较,一致的话就认证成功。String authenticationEncoding = Base64.getEncoder().encodeToString(new String(username + ":" + password).getBytes());if(proxy_Authorization.equals(authenticationEncoding)){isLogin = true;//登录通过//log("login success, basic: %s", proxy_Authorization);}else {log("httpproxy server need login,but login failed .");}
}
  1. ##如果不需要登陆,或认证成功,进一步进行是http还是https的判断,分别作不同的处理
//根据HTTP method来判断是https还是http请求
if ("CONNECT".equalsIgnoreCase(type)) {//https先建立隧道lout.write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes());lout.flush();
}else {//http直接将请求头转发rout.write(headStr.toString().getBytes());rout.flush();
}
  1. ##最后作真正的数据转发即可

3.通过http代理进行内网安装yum软件

生产环境,常常是不给服务器有互联网访问的权限的,要进行yum安装一些软件,就有点麻烦,常用的做法有,在内网搭建一个私库,然后通过私库进行安装,见另一篇nexus3私库环境搭建(maven,yum,apt,nodejs), 或者进行离线rpm安装等,本篇采用http代理服务器+securt远程透传的方式进行,还是较简单的。

3.1 步骤2实现的代理服务器启动

一般我本地笔记本肯定是有外网访问权限的,连本地个人电脑都没有外网访问,就没办法了,先进行代理服务器的启动如下:

##这里指定了以1080端口启动,并默认是开了认证的,账号admin密码admin123
java -server -Xmx256m -Xms256m -Xmn128m ProxyHttpsServer 1080


##代理服务器启动成功截图:

3.2通过securecrt进行远程内网服务器的连接

一般可以通过vpn或其他方式能在个人笔记本电脑上直接连进远程的内网服务器,
连接远程服务器后,通过securecrt自带的远程端口透传功能进行远程端口到本地端口的反向映射

如下:通过crt连接我的内网服务器192.168.56.101,然后通过crt作一个远程到本地的端口转发,(其实这里我的192.168.56.101是能直连我的本地电脑192.168.56.1,但为了模拟只能单向从本地到远程,因此这里通过crt作一个远程到本地的反向转发)

经过以上的端口转发配置后,通过在服务器192.168.56.101上进行访问127.0.0.1:11080就相当于访问到我的本地电脑的192.168.56.1的1080了,测试如下:

因为我没有装telnet,因此采用curl测试端口情况,在192.168.56.101上执行curl http://127.0.0.1:11080, 显示Empty reply from server,其实是成功的。看本地的程序日志也能看出来有请求到达。说明端口从远程到本地是成功的。

3.3 进行export配置通过http代理访问

在远程服务器上进行export三条命令的执行,告诉服务器,通过代理访问相关资源。
注:export命令只对当前session生效,即关了crt再进入服务器时,要重新执行

export http_proxy=http://admin:admin123@127.0.0.1:11080
export https_proxy=http://admin:admin123@127.0.0.1:11080
export no_proxy='127.0.0.1'

上面的no_proxy是告诉服务器127.0.0.1相关的地址不需要走代理

以访问www.baidu.com为例,执行命令行,访问不了:

执行export后再执行curl http://www.baidu.com测试

3.4 通过代理进行yum软件的安装

由于3.3配置后,能在远程内网访问直接访问外面的网站了,因此,接下来正常直接按yum操作执行软件安装即可了,如:

yum install -y telnet

安装日志正常,软件能正常安装,超级方便,相当于有外网状态下进行相关的yum软件安装

本地的代理程序,也显示已通过代理进行远程的yum.repo网址的访问,说明是真的通过代理服务器走资源的访问并转发。

4. 总结

本文讲述了如何通过Java实现一个http代理服务器,并进行简单的应用。如yum软件的安装等,另外,sock5代理服务器的原理与实现,以及应用也类似,后面再写一个Java版的Sock5代理服务器的实现及应用,如对这篇文章有什么疑问,请指正或回复我。

Java实现Http代理服务器通过http代理进行内网安装yum软件相关推荐

  1. 端口转发与代理工具 内网代理 内网反弹代理

    目录 一.LCX 二.nc 反弹 三.socks代理工具 四.frp 内网穿透利器 五.ngrok 内网穿透 理论上,任何接入互联网的计算机都是可访问的,但是如果目标主机处于内网,而我们又想和该目标主 ...

  2. 红蓝对抗之隧道技术第一篇(内网穿透、端口映射端口转发、Netsh端口转发、CS正反向连接多层内网、Burp设置上游代理访问内网、MSF protfwd端口转发/重定向)

    文章目录 隧道应用 端口映射&端口转发 Netsh端口转发 Netsh端口转发meterpreter CS正向连接多层内网 CS反向连接多层内网 Burp设置上游代理访问内网 MSF prot ...

  3. ssh代理登录内网服务器

    ssh代理登录内网服务器 服务器 192.168.48.81 # client 192.168.48.82 # bastion 192.168.48.83 # private password方式 1 ...

  4. nginx做正向代理http,内网主机yum安装外网资源

    一.概念解释(基本解释详细可以百度) 正向代理:内网通过nginx请求外部url 反向代理:外部通过nginx请求内部服务器 二.配置简图 192.168.1.11类似内网,不能直接访问www.abc ...

  5. 搭建我的世界java版服务器,公网远程联机【内网穿透】

    文章目录 1. 搭建我的世界服务器 1.1 服务器安装java环境 1.2 配置服务端 2. 测试局域网联机 3. 公网远程联机 3.1 安装cpolar内网穿透 3.1.1 windows系统 3. ...

  6. 利用EW代理实现内网穿透

    利用EW代理实现内网穿透 环境: 攻击机:kali ip192.168.32.132 中间机:win7 ip 192.168.32.128 ip2 192.168.1.3 假定为公网vps 内网主机: ...

  7. 宿主机使用虚拟机中的全局代理访问内网

    如何让宿主机使用虚拟机中的全局代理访问内网 背景 方法 配置VirtualBox 虚拟机下网络配置 最后的操作 背景 因为公司使用的 VPN 只有 Windows 客户端,所以只好在虚拟机中的 Win ...

  8. NetOk(免费反向代理)+访问内网网站

    我们需要使用到的工具软件 NetOk(免费反向代理)( https://netok.link/a/download/) 首先我们需要将工具软件拷贝到需要进行远程调试的电脑上,进行一些简单配置,既可使用 ...

  9. 信创环境下Nginx正向代理实现内网发送邮件

    背景 标题党了,其实不管是不是在信创环境,只要存在网络分区/隔离,我们都可能面临发送邮件的问题: 业务服务要发送邮件但是部署在无法连接互联网的环境A中: Nginx一方面作为静态资源服务,另一方面作为 ...

最新文章

  1. 一顿“寄生虫大餐”,或能治好干净引来的免疫病
  2. c# 因其保护级别而不可访问。只能处理公共类型。
  3. ActiveMQ中Queue生产者
  4. vacantcell缓存分析
  5. selenuim自动化爬取汽车在线谷米爱车网车辆GPS数据爬虫
  6. 短语密码_使用密码短语以提高安全性
  7. 用英语描述计算机操作,操作系统的英文介绍
  8. 时间序列研(part14)--习题
  9. 安装VMWare Tools教程
  10. Ubuntu cd 命令
  11. 基于Java 生产者消费者模式(详细分析)
  12. git获取所有branch_获取Git仓库的所有分支名字
  13. npm install 连接不上github解决办法
  14. 2021/7/14 java小结
  15. Activiti7工作流引擎:基础篇(七) 流程变量
  16. Linux Watchdog/看门狗
  17. 关于市盈率市净率的探讨
  18. nuxt中图片预加载
  19. 应用覆盖安装后桌面图标消失问题
  20. 一款基于SpringBoot2.x, springcloud G版本的后台管理系统java源码—RuoYi-plus管理平台系统模板(商城、OA、CRM等二次开发)

热门文章

  1. Java Web 网络商城案例演示五(用户激活)
  2. PHP常用的非对称加密
  3. 如何零基础自学java_如何零基础自学Java?
  4. python绘制国内生产总值散点图_用Python分析国民生产总值
  5. matlab仿真产生条纹,光的干涉与衍射的Matlab仿真及其实验观测.PDF
  6. 一年半经验的前端面经总结
  7. 我用wxPython搭建GUI量化系统之财务选股工具与股票行情界面切换
  8. 美业SaaS的创业分享之[策略]:用免费换流量并不是一个好主意
  9. 奈雪的茶什么情况,上市第一天就跌了15%!
  10. 报错:struts之invalid field value for field