对 node的 https 正向代理的流程分析
/*
* @Author: LingMax
* @Date: 2020-08-27 17:18:04
* @Description: 对 node的 https 代理的研究
*/
const http = require('http'),
https = require('https');
var net = require('net');
var tls = require('tls');
var options = {
key:
`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA6qJGOKpTSUKRo8FiYnCosyrkPpAjOdNmpgQmM1ZYRTOOM30M
TwUbYB5rR37Yf+JDtadUYonMsd6u+1Oa1TVbDByo9eiETscv4I/4KhVZqKSP3XmO
fNWN9KgQ+l0RRw6g5utsFUTe/rbEnn5vQ43eAtZZOCEb6mPJoFbHcBTCWnnqGgUn
an2bzGwJ7wUrYeK5iRvc6p55CqoNN9sbUFsv+L+XKc9UskN+b9t3JCynyQHt6ZSt
1PwtzoSWtoca2uQBRmRQocoVzz5WEIctj6b9zA10L6gb7niNhWxc5Q2ZD0NDr4aV
8W5uDqHexGBpckWuQQZw5hr6pIUACsEoEruMgwIDAQABAoIBAQCUjHCQ56UbOL4k
Qwca8+Caroka4v6qWaEfcnkM/5mbFmztRDpKvRz72cZp2XEQZhwgIfRW/o9N/YIj
NGdOnR0rqel+5tr9VTaGoh+n5SSClM1QlukTN9FMGCvHlqydpDFSgbJINPZJpUUO
Y1XmGyd3/GU4GB4oY0z/6nESENKLnHWzQWjaSDzIw2LmZ8XHkFDYzoq1LmAwM+1c
Zfsd08mHZeqn9SOFf/6dgQgC8FA+Ms5NfKL6PZIij0eTm2gzXEXxgdAs7Yft8HuZ
2us7fbUpui2rrvXejfAvdS42N8ixB0m0GmG8qSjhjMZBUtupzcTgtignsxkXBdIC
XqMAmIthAoGBAPf5XU8CFrOIwtr3PYVrUycr5ONoyp0QgLZ6+QFwf2bN9QsRgd3Y
LQ6hdxol9yzLMtoH66VeEro7hSXwjN/7dh3nbAc3alE3dGRlIRUaeQdcFOod5iGR
Q7+F6PiymnrFl3QSE+dWi6VksxNP6guSR0AZdxfBmTHTcVgCgSgCGlb1AoGBAPI6
YIu0upOO6FDK2MZSbfSuHiZs6toij6Ah7MpPHstksU/qM9/4WP8cTqkhGokXtBmU
pGpGr1Q7Ab9JGw4JrXRTvgIZg3+d+xiTGUL9gMhp5127y5fojDPRIdK9dO04UlTD
s1sFiFlLGqa+XtdRiQN5gG+8zvoWp6cX3jyIy/qXAoGBAI+XqL6dmQOxiBQ/4zIl
Keue8VX2Uo2NBtukbhi1SjD/xov4QVlzWvQD7/IGVhFsQTAcMgp6ZSHOYZXMq+bv
uEAsyFONdVU+ZXnVTcjooXjvi3Teh2qcsbxwEK4izm2VidQ+u6PUa90EaOYf+olk
1Tl7BYmOI+XEaPfry1qdjR8ZAoGAI4XSIMrZTch4Y1jMH5F5FJfwTfxNGL5Wx8oR
2r1tq7BRnIGhJ+hYzNjO5Fi5dn9mZxX4YqmJDtY0dGP5Nr7OlC+vvskVEsMNTtZL
rxpUJ4/4YTOoMNfmr7asuiYUnrFSyaGFjQSrsUSlXOywJe2MJVlNL5XF2ME3xvZm
HgSFvXMCgYBEDApapNjl64KOJFanu7bDflo1Nkjldehhof5IhaAXXKMqZBZscKiS
4gpHGP48kmyFsJSwO3vl5A8Vn/7/kkU/XAnRt1ymfnMb53/9vgOdT0+vC8b0HJX1
elkf6zv5Pw17r0RWsYBWxEvCgWsZz7rnm3OGDCzeYfTI9b/he5m6vA==
-----END RSA PRIVATE KEY-----
`,
cert:
`-----BEGIN CERTIFICATE-----
MIIEDTCCAvWgAwIBAgIDBkaIMA0GCSqGSIb3DQEBCwUAMIGAMQswCQYDVQQGEwJD
TjEcMBoGA1UEChMTTGluZ01heCBIVFRQUyBQcm94eTELMAkGA1UECBMCU0gxKDAm
BgNVBAsTH0xpbmdNYXggU1NMIFByb3h5IGZyb20gQW55UHJveHkxHDAaBgNVBAMT
E0xpbmdNYXggSFRUUFMgUHJveHkwHhcNMTAwMzIxMTgxNjU4WhcNMzAwMzIxMTgx
NjU4WjCBgDELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE0xpbmdNYXggSFRUUFMgUHJv
eHkxCzAJBgNVBAgTAlNIMSgwJgYDVQQLEx9MaW5nTWF4IFNTTCBQcm94eSBmcm9t
IEFueVByb3h5MRwwGgYDVQQDExNMaW5nTWF4IEhUVFBTIFByb3h5MIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6qJGOKpTSUKRo8FiYnCosyrkPpAjOdNm
pgQmM1ZYRTOOM30MTwUbYB5rR37Yf+JDtadUYonMsd6u+1Oa1TVbDByo9eiETscv
4I/4KhVZqKSP3XmOfNWN9KgQ+l0RRw6g5utsFUTe/rbEnn5vQ43eAtZZOCEb6mPJ
oFbHcBTCWnnqGgUnan2bzGwJ7wUrYeK5iRvc6p55CqoNN9sbUFsv+L+XKc9UskN+
b9t3JCynyQHt6ZSt1PwtzoSWtoca2uQBRmRQocoVzz5WEIctj6b9zA10L6gb7niN
hWxc5Q2ZD0NDr4aV8W5uDqHexGBpckWuQQZw5hr6pIUACsEoEruMgwIDAQABo4GN
MIGKMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgL0MDsGA1UdJQQ0MDIGCCsGAQUF
BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCDARBglg
hkgBhvhCAQEEBAMCAPcwHQYDVR0OBBYEFHnWjPVcADCvTcMyVeZqUnE0ApbDMA0G
CSqGSIb3DQEBCwUAA4IBAQCJkjuBJxk8Q4th+PWn4Fsb0YZog3NL9ayf54kI5A6t
+RAyKTuP21ErkS9QofzI24PaA2UiRl4sMtWhAiM68gbMJsDcTKUVPlvOhr3GAChY
LOFYz97vhAKsYbz4NLZ0MxTc6PJgsDYpy5DrGTdbUuwPjXaAW2oHEHV3Z/+yGR9m
YUMemYgRZFeW/CWWTQiraqYT/bE5jUMN/8RwoQGrlmgirKWvD4iCeVLwHFjOuEf2
f27DzGaHsF2BuSy45H4Luk6gTsFVIzyXYxKvTBNphxQ6AKkI/QQAiidjyGLF4DmX
hfvymqUQ7y/oyL75ZQ7eSY++zi/c5Ikbl2sRUzPVOygA
-----END CERTIFICATE-----
`
};
//创建http服务
http.createServer({},function(req, res){
res.writeHead(200, {'Content-type' : 'text/html'});
res.write('<h1>http</h1>');
res.end('<p> World</p>');
}).listen(88);
//创建https服务 虽然是http 但是 https数据流解密后会转发到这里来 这里专门处理https
http.createServer({},function(req, res){
res.writeHead(200, {'Content-type' : 'text/html'});
res.write('<h1>https</h1>');
res.end('<p> World</p>');
}).listen(89);
//测试普通https 服务
https.createServer(options,function(req, res){
res.writeHead(200, {'Content-type' : 'text/html'});
res.write('<h1>ssss</h1>');
res.end('<p> World</p>');
}).listen(86);
//http与https代理端口合并一起用 也是对外的总端口
net.createServer(function(socket){
socket.once('data', function(buf){
console.log(buf[0]);
// https数据流的第一位是十六进制“16”,转换成十进制就是22
var port = (buf[0] === 22 ? 87 : 88);
//创建一个转发tcp的连接
var proxy = net.createConnection(port, function() {
proxy.write(buf);
//反向代理的过程,tcp接受的数据交给代理链接,代理链接服务器端返回数据交由socket返回给客户端
socket.pipe(proxy).pipe(socket);
});
proxy.once('error', function(err) {
console.log(err);
proxy.destroy();
});
});
socket.on('error', function(err) {
console.log(err);
});
}).listen(8080);
//https 数据流服务 这个也成功 但是区分https好点
tls.createServer(options, (socket) => {
// console.log('server connected',socket.authorized ? 'authorized' : 'unauthorized');
// socket.on('data',function (d) {
// socket.setEncoding('utf8');
// console.log(d);
// socket.write(
// `HTTP/1.1 200 OK
// Date: Mon, 31 Aug 2020 06:02:27 GMT
// Content-Type: text/html
// Content-Length: 5
// 123456`);
// })
//创建一个指向https或http服务器的链接
var proxy = net.createConnection(89, function() {
//proxy.write(buf);
//反向代理的过程,tcp接受的数据交给代理链接,代理链接服务器端返回数据交由socket返回给客户端
socket.pipe(proxy).pipe(socket);
});
proxy.once('error', function(err) {
console.log(err);
proxy.destroy();
});
// socket.pipe(socket);
}).listen(88, () => {
console.log('https server bound');
});
// 备注 如果要区分ip 得做一个映射表 映射出转发的ip与端口