我正在尝试编写一个 tcp 流“隧道”(类似于默认情况下 SSH 处理的那些),但有一个例外,我必须在某些信息流过时重写它。
我确定那里有类似的东西,但我一直找不到。我有三个主要问题:
- 有没有一种简单的方法可以保存 tcp 流以供观察?(即使用 netcat,或 ssh -r/-l/-D,或一起使用其他一些实用程序)
- 动态重写流有多难?
编辑:被重写的信息将只是初始身份验证。
我正在尝试编写一个 tcp 流“隧道”(类似于默认情况下 SSH 处理的那些),但有一个例外,我必须在某些信息流过时重写它。
我确定那里有类似的东西,但我一直找不到。我有三个主要问题:
编辑:被重写的信息将只是初始身份验证。
可以从现有的(或容易找到的)公用设施拼凑出一条带有测井功能的直通隧道。
socat -v -x tcp-l:8080,fork,reuseaddr tcp:localhost:80 2>log
在此示例中,连接到http://localhost:8080/
将传递到http://localhost:80/
,并记录传输到 的数据log
。
TCPreen工具专门用于此目的。
如果你有 root 权限,有很多分析器,例如tcpdump和tcpflow,可以直接从网络捕获数据包,而无需重定向流量。
socat
,cr
还可以使用and选项进行一些非常基本的流修改,这些,crnl
选项可以去除/添加/替换\r
字符。
无论如何,回到最初的问题……自从我编写任何 Java 以来已经有很长时间了,这完全未经测试,但是可以在重新传输之前修改流量的隧道并不难。
public class ForwardAndChangeCaseThread extends Thread {
private Socket in, out;
public ForwardAndChangeCaseThread(Socket in, Socket out) {
this.in = in; this.out = out;
}
public void run() {
byte[] buf = new byte[4096];
InputStream in = this.in.getInputStream();
OutputStream out = this.out.getOutputStream();
int count;
while ((count = in.read(buf)) > 0) {
for (int i = 0; i < count; i++)
if (buf[i] >= 0x40) buf[i] ^= 0x20;
out.write(buf, 0, count);
}
}
}
public class TcpForwarder {
public static void main(String[] args) {
ServerSocket listen = new ServerSocket(8080, 1);
for (;;) {
Socket local = listen.accept();
Socket remote = new Socket("localhost", 80);
new ForwardAndChangeCaseThread(local, remote).start();
new ForwardAndChangeCaseThread(remote, local).start();
}
}
}
不要自吹自擂,但我在很久以前为异步 IO 编写的框架中编写了一些代码来实现这一点。现在有很多关于代码的东西已经过时了,但它确实有效。这是它的网页链接:
我写的那个做你想要的隧道的东西叫做 PortForward,还有一些东西会转储出一个 TCP 流,但我忘记了我叫它什么。由于框架的工作方式,它们可以轻松组合。
如果您需要帮助使用它来实现该目标,我会回来的。正如其他人指出的那样,不可能即时重写 SSL 流。因此,如果您的连接使用加密和/或 MAC(如果是 SSL,这是正确的一种方式),那么您就不走运了。
我不确定这是否是您要问的,但是...
除非您拥有服务器 SSL 证书的私钥,否则您无法即时重写 SSL 流……或者您可以在不受 SSL 保护的某个点(在客户端或服务器地址空间中)拦截它。如果可以,SSL 将是浪费时间。
同样,如果您捕获 SSL 流的全部内容(双向),除非您拥有相关的私钥,否则对您没有好处。