咳咳,各位观众老爷们,晚上好!今天咱们来聊聊一个既能让你抓包爽歪歪,又能让你差点进局子的技术:JS Proxy Server
配置与 Man-in-the-Middle
(MITM) 攻击。
友情提示: 以下内容仅供技术学习和安全研究,请勿用于非法用途。否则,后果自负,本讲座概不负责。出了事儿别说是听我讲的!
开场白:什么是Proxy Server?
简单来说,代理服务器就像一个中间人,你和目标服务器之间所有的数据都得经过它。你可以把它想象成一个快递驿站,你的包裹(数据)先送到驿站(代理服务器),驿站再帮你转发到你家(目标服务器)。
Proxy Server的作用
- 访问限制网站: 比如,某些网站限制了特定地区的访问,你可以通过代理服务器绕过这些限制。
- 隐藏真实IP地址: 代理服务器可以隐藏你的真实IP地址,保护你的隐私。
- 加速访问: 某些代理服务器可以缓存数据,加速你的访问速度。
- 抓包分析: 这是咱们今天的主角!通过代理服务器,我们可以拦截、修改、甚至伪造HTTP/HTTPS请求和响应,从而分析网络协议、调试程序,甚至进行一些…你懂的…事情。
JS Proxy Server:为啥用JS?
传统的代理服务器(比如Nginx、Squid)通常用C/C++编写,配置复杂,不易扩展。而JS Proxy Server,尤其是基于Node.js的,具有以下优点:
- 易于上手: JavaScript上手简单,开发效率高。
- 高度可定制: 可以用JS编写自定义的代理逻辑,灵活处理各种场景。
- 跨平台: Node.js可以运行在各种操作系统上。
- 生态丰富: Node.js生态系统提供了大量的第三方库,可以方便地实现各种功能。
搭建一个简单的JS Proxy Server
咱们用Node.js和http-proxy
库来搭建一个最简单的HTTP代理服务器。
-
安装依赖:
npm install http-proxy
-
编写代码:
const http = require('http'); const httpProxy = require('http-proxy'); // 创建代理服务器 const proxy = httpProxy.createProxyServer({}); // 监听代理服务器的错误事件 proxy.on('error', function (err, req, res) { console.error(err); res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong. And we are reporting a custom error message.'); }); // 创建HTTP服务器 const server = http.createServer(function(req, res) { // 将请求代理到目标服务器 proxy.web(req, res, { target: 'http://example.com' // 替换成你想要代理的目标服务器 }); }); console.log("listening on port 3000") server.listen(3000);
代码解释:
http
和http-proxy
是Node.js内置的HTTP模块和http-proxy
库。httpProxy.createProxyServer({})
创建了一个代理服务器实例。proxy.on('error', ...)
监听代理服务器的错误事件,防止程序崩溃。http.createServer(function(req, res) { ... })
创建一个HTTP服务器,接收客户端的请求。proxy.web(req, res, { target: 'http://example.com' })
将客户端的请求代理到目标服务器http://example.com
。
-
运行代码:
node your_proxy_file.js
现在,你的代理服务器就在
localhost:3000
上运行了。 -
配置客户端:
在你的浏览器或者HTTP客户端中,将代理服务器设置为
localhost:3000
。 例如,在Chrome浏览器中,你可以通过以下步骤设置代理:- 打开Chrome设置
- 搜索“代理”
- 打开“打开您计算机的代理设置”
- 选择“手动设置代理”
- 填写代理服务器地址和端口号。
现在,当你访问任何网站时,所有的请求都会经过你的代理服务器。
进阶:拦截和修改HTTP请求
光是转发请求太没意思了,咱们来点刺激的,拦截和修改HTTP请求。
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
proxy.on('proxyReq', function (proxyReq, req, res, options) {
// 修改请求头
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
// 打印请求信息
console.log('Request URL:', req.url);
});
proxy.on('proxyRes', function (proxyRes, req, res) {
// 修改响应头
proxyRes.headers['X-Custom-Header'] = 'Hello from proxy!';
// 打印响应状态码
console.log('Response Status:', proxyRes.statusCode);
});
const server = http.createServer(function(req, res) {
proxy.web(req, res, {
target: 'http://example.com'
});
});
console.log("listening on port 3000")
server.listen(3000);
代码解释:
proxy.on('proxyReq', ...)
监听proxyReq
事件,该事件在请求发送到目标服务器之前触发。我们可以在这里修改请求头。proxy.on('proxyRes', ...)
监听proxyRes
事件,该事件在收到目标服务器的响应之后触发。我们可以在这里修改响应头。
更进一步:拦截和修改HTTP响应体
修改请求头和响应头还不够,咱们来修改响应体,这才是真正的黑魔法!
const http = require('http');
const httpProxy = require('http-proxy');
const zlib = require('zlib');
const proxy = httpProxy.createProxyServer({});
proxy.on('proxyRes', function (proxyRes, req, res) {
let body = [];
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', function () {
body = Buffer.concat(body).toString();
// 修改响应体
let modifiedBody = body.replace('example', 'HACKED!');
// 发送修改后的响应
res.writeHead(proxyRes.statusCode, proxyRes.headers);
res.end(modifiedBody);
});
});
const server = http.createServer(function(req, res) {
proxy.web(req, res, {
target: 'http://example.com'
});
});
console.log("listening on port 3000")
server.listen(3000);
代码解释:
- 我们首先监听
proxyRes
事件。 - 在
proxyRes.on('data', ...)
中,我们将响应体的数据块收集到body
数组中。 - 在
proxyRes.on('end', ...)
中,我们将body
数组转换为字符串,并使用replace()
方法修改响应体。 - 最后,我们使用
res.writeHead()
和res.end()
方法发送修改后的响应。
重要提示: 如果响应体是经过压缩的(比如gzip),你需要先解压缩,修改后再压缩。zlib
模块可以帮助你完成这个任务。
HTTPS代理:如何抓取HTTPS流量?
HTTPS使用SSL/TLS加密,保证数据传输的安全性。直接用HTTP代理无法抓取HTTPS流量,因为数据是加密的。
要抓取HTTPS流量,我们需要进行中间人攻击 (MITM)。
MITM攻击原理:
- 客户端向代理服务器发起HTTPS请求。
- 代理服务器伪装成目标服务器,向客户端发送一个伪造的SSL/TLS证书。
- 客户端信任该证书(或者你手动信任),并与代理服务器建立HTTPS连接。
- 代理服务器与目标服务器建立HTTPS连接。
- 代理服务器解密客户端发送的数据,并加密后发送给目标服务器。
- 代理服务器解密目标服务器发送的数据,并加密后发送给客户端。
通过这种方式,代理服务器就可以拦截、修改和分析HTTPS流量。
实现HTTPS代理的步骤:
-
生成自签名证书:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
这会生成两个文件:
key.pem
(私钥) 和cert.pem
(证书)。 -
安装mitmproxy:
mitmproxy是一个强大的HTTPS代理工具,可以自动生成和管理证书。
pip install mitmproxy
-
运行mitmproxy:
mitmproxy
mitmproxy会生成一个CA证书,你需要手动安装到你的操作系统和浏览器中,才能信任mitmproxy生成的证书。
-
配置客户端:
将客户端的代理服务器设置为mitmproxy的地址(默认是
localhost:8080
)。
注意事项:
- 安全风险: MITM攻击会降低HTTPS的安全性,因为代理服务器可以解密和修改数据。请谨慎使用。
- 证书信任: 你需要手动信任代理服务器生成的证书,否则浏览器会提示安全警告。
- 法律风险: 在未经授权的情况下,进行MITM攻击是违法的。
JS 实现简单的HTTPS Proxy (不推荐生产环境使用,仅供学习):
虽然 mitmproxy 很好用,但为了学习,我们可以尝试用 JS 来实现一个简单的 HTTPS Proxy。 这个例子仅仅演示原理,不具备生产环境的安全性。
const https = require('https');
const http = require('http');
const tls = require('tls');
const fs = require('fs');
// 生成的证书
const options = {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem'),
};
const httpsProxy = http.createServer((req, res) => {
// 处理HTTP请求,这里省略,可以参考之前的HTTP Proxy例子
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello from HTTP proxyn');
});
httpsProxy.on('connect', (req, socket, head) => {
// 拦截CONNECT请求,建立TLS隧道
const url = req.url.split(':');
const hostname = url[0];
const port = parseInt(url[1], 10);
// 建立与目标服务器的连接
const tlsSocket = tls.connect(port, hostname, {}, () => {
// 通知客户端连接已建立
socket.write('HTTP/1.1 200 Connection Establishedrnrn');
// 开始双向转发数据
tlsSocket.pipe(socket);
socket.pipe(tlsSocket);
});
tlsSocket.on('error', (err) => {
console.error('TLS Socket Error:', err);
socket.write('HTTP/1.1 502 Bad Gatewayrnrn');
socket.destroy();
});
socket.on('error', (err) => {
console.error('Socket Error:', err);
tlsSocket.destroy();
});
});
const secureProxy = https.createServer(options, (req, res) => {
//处理 HTTPS 请求,这里需要自己实现完整的 MITM 逻辑,比较复杂,这里简单返回
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello from HTTPS proxy (MITM)n');
});
console.log("listening on port 3000 (HTTP) and 3001 (HTTPS)")
httpsProxy.listen(3000);
secureProxy.listen(3001);
重要说明:
- 安全性: 这个简单的HTTPS代理存在严重的安全漏洞,比如无法验证目标服务器的证书,容易受到中间人攻击。请勿在生产环境中使用!
- 复杂性: 完整的HTTPS代理需要处理各种复杂的TLS协议细节,包括证书验证、密钥协商、加密解密等。
- mitmproxy的优势: mitmproxy已经为你处理了这些复杂性,并提供了强大的功能,比如流量过滤、修改、重放等。
MITM攻击的道德与法律边界
MITM攻击是一把双刃剑。它可以用于安全研究、漏洞挖掘、协议分析等,但也可以用于非法窃取用户数据、篡改信息等。
在进行MITM攻击之前,请务必明确以下几点:
- 法律法规: 了解你所在国家或地区的法律法规,确保你的行为不违法。
- 授权许可: 获得目标系统的授权许可,才能进行安全测试。
- 用户隐私: 尊重用户隐私,不要窃取或泄露用户敏感信息。
总结:
技术点 | 描述 | 风险等级 | 适用场景 |
---|---|---|---|
HTTP Proxy | 搭建简单的HTTP代理服务器,可以转发HTTP请求,修改请求头和响应头,修改响应体。 | 低 | 调试HTTP接口,分析网络协议,修改网页内容(例如,去除广告)。 |
HTTPS Proxy (MITM) | 通过中间人攻击,拦截和解密HTTPS流量,可以分析和修改HTTPS请求和响应。 | 高 | 安全研究,漏洞挖掘,协议分析。 |
mitmproxy | 强大的HTTPS代理工具,可以自动生成和管理证书,提供流量过滤、修改、重放等功能。 | 中 | 同 HTTPS Proxy(MITM),但工具更易用,功能更强大。 |
最后的忠告:
技术是中立的,但使用技术的人是有立场的。请始终牢记你的责任,遵守法律法规,尊重用户隐私。
好了,今天的讲座就到这里。希望大家有所收获,也希望大家不要因此被请去喝茶。咱们下期再见!