From cc75c4e1816fa02e7aa6b58820ee6bded9795dd3 Mon Sep 17 00:00:00 2001 From: avwo Date: Wed, 15 Dec 2021 00:27:09 +0800 Subject: [PATCH] feat: add originalReq.remoteAddress & originalReq.remotePort --- lib/config.js | 2 ++ lib/https/index.js | 12 ++++++++---- lib/init.js | 2 ++ lib/plugins/index.js | 2 ++ lib/plugins/load-plugin.js | 10 ++++++---- lib/tunnel.js | 2 ++ lib/upgrade.js | 8 ++++++-- lib/util/index.js | 16 +++++++++++++--- 8 files changed, 41 insertions(+), 13 deletions(-) diff --git a/lib/config.js b/lib/config.js index c49a7e19c..cb1a26415 100644 --- a/lib/config.js +++ b/lib/config.js @@ -60,6 +60,8 @@ config.CLIENT_PORT_HEAD = 'x-whistle-client-port'; config.WEBUI_HEAD = 'x-forwarded-from-whistle-' + uid; config.RES_RULES_HEAD = 'x-whistle-res-rules-' + uid; config.CLIENT_INFO_HEAD = 'x-whistle-client-info-' + uid; +config.REMOTE_ADDR_HEAD = 'x-whistle-remote-addr'; +config.REMOTE_PORT_HEAD = 'x-whistle-remote-port'; config.WEBUI_PATH = '/.whistle-path.5b6af7b9884e1165/'; config.PREVIEW_PATH_RE = /\?\?\?WHISTLE_PREVIEW_CHARSET=([A-Z\d_-]+)\?\?\?$/; config.PLUGIN_HOOK_NAME_HEADER = 'x-whistle-plugin-hook-name_'; diff --git a/lib/https/index.js b/lib/https/index.js index 42f481f2b..f5eb5f0f1 100644 --- a/lib/https/index.js +++ b/lib/https/index.js @@ -38,11 +38,11 @@ var proxy, server; function handleWebsocket(socket, clientIp, clientPort) { var wss = socket.isHttps; - clientIp = util.removeIPV6Prefix(clientIp || socket.remoteAddress); + clientIp = util.removeIPV6Prefix(clientIp || socket._remoteAddr || socket.remoteAddress); socket.clientIp = clientIp; socket.method = 'GET'; socket.reqId = util.getReqId(); - socket.clientPort = clientPort || socket.remotePort; + socket.clientPort = clientPort || socket._remotePort || socket.remotePort; rules.initHeaderRules(socket); pluginMgr.resolvePipePlugin(socket, function() { socket.rules = rules.initRules(socket); @@ -745,7 +745,8 @@ function addReqInfo(req) { if (remoteData) { req.isHttpH2 = remoteData.isHttpH2; socket._remoteDataInfo = remoteData; - headers[config.CLIENT_INFO_HEAD] = (remoteData.clientIp || LOCALHOST) + ',' + remoteData.clientPort; + headers[config.CLIENT_INFO_HEAD] = (remoteData.clientIp || LOCALHOST) + ',' + remoteData.clientPort + + ',' + remoteData.remoteAddr + ',' + remoteData.remotePort; var tunnelFirst = remoteData.tunnelFirst; if (remoteData.clientId) { headers[config.CLIENT_ID_HEADER] = remoteData.clientId; @@ -912,7 +913,8 @@ var CONNECT_RE = /^CONNECT$/i; function addClientInfo(socket, chunk, statusLine, clientIp, clientPort) { var len = Buffer.byteLength(statusLine); chunk = chunk.slice(len); - statusLine += '\r\n' + config.CLIENT_INFO_HEAD + ': ' + clientIp + ',' + clientPort; + statusLine += '\r\n' + config.CLIENT_INFO_HEAD + ': ' + clientIp + ',' + clientPort + + ',' + socket._remoteAddr + ',' + socket._remotePort; var clientId = socket.headers[config.CLIENT_ID_HEADER]; if (clientId) { statusLine += '\r\n' + config.TEMP_CLIENT_ID_HEADER + ': ' + clientId; @@ -1032,6 +1034,8 @@ module.exports = function(socket, next, isWebPort) { tunnelTmplData.set(reqSocket.localPort + ':' + reqSocket.remotePort, { clientIp: clientIp, clientPort: clientPort, + remoteAddr: socket._remoteAddr, + remotePort: socket._remotePort, clientId: headers[config.CLIENT_ID_HEADER], proxyAuth: disable.tunnelAuthHeader ? undefined : headers['proxy-authorization'], tunnelData: tunnelData, diff --git a/lib/init.js b/lib/init.js index ac9baac45..fc410cba4 100644 --- a/lib/init.js +++ b/lib/init.js @@ -159,6 +159,8 @@ module.exports = function(req, res, next) { var socket = req.socket || {}; var clientInfo = util.parseClientInfo(req); var clientIp = clientInfo[0] || util.getForwardedFor(headers); + req._remoteAddr = clientInfo[2] || util.getRemoteAddr(req); + req._remotePort = clientInfo[3] || util.getRemotePort(req); if (clientIp && util.isLocalAddress(clientIp)) { delete headers[config.CLIENT_IP_HEAD]; clientIp = null; diff --git a/lib/plugins/index.js b/lib/plugins/index.js index f1bba2524..bc19bfd6d 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -524,6 +524,8 @@ function addRuleHeaders(req, rules, headers, isPipe) { } else { delete headers[FROM_TUNNEL_HEADER]; } + headers[config.REMOTE_ADDR_HEAD] = req._remoteAddr || LOCALHOST; + headers[config.REMOTE_PORT_HEAD] = req._remotePort || '0'; if (req.fromComposer) { headers[config.REQ_FROM_HEADER] = 'W2COMPOSER'; } else { diff --git a/lib/plugins/load-plugin.js b/lib/plugins/load-plugin.js index 1413fa66f..7cb3f3066 100644 --- a/lib/plugins/load-plugin.js +++ b/lib/plugins/load-plugin.js @@ -398,11 +398,11 @@ var initReq = function(req, res, isServer) { req.customParser = oReq.customParser = notEmptyStr(parseStatus); req.customParser && addParserApi(req, res, parseStatus, reqId); } - var headers = extractHeaders(req, pluginKeyMap); + var conf = pluginOpts.config; req[REQ_ID_KEY] = oReq.id = reqId; addSessionStorage(req, reqId); - oReq.headers = headers; - oReq.isHttp2 = oReq.isH2 = !!req.headers[pluginOpts.config.ALPN_PROTOCOL_HEADER]; + oReq.headers = extractHeaders(req, pluginKeyMap); + oReq.isHttp2 = oReq.isH2 = !!req.headers[conf.ALPN_PROTOCOL_HEADER]; oReq.existsCustomCert = req.headers[pluginOpts.CUSTOM_CERT_HEADER] == '1'; oReq.isUIRequest = req.isUIRequest = req.headers[pluginOpts.UI_REQUEST_HEADER] == '1'; oReq.enableCapture = req.headers[pluginOpts.ENABLE_CAPTURE_HEADER] == '1'; @@ -413,9 +413,11 @@ var initReq = function(req, res, isServer) { oReq.sniValue = getValue(req, pluginOpts.SNI_VALUE_HEADER); oReq.hostValue = getValue(req, pluginOpts.HOST_VALUE_HEADER); oReq.url = oReq.fullUrl = getValue(req, pluginOpts.FULL_URL_HEADER); + oReq.remoteAddress = req.headers[conf.REMOTE_ADDR_HEAD] || '127.0.0.1'; + oReq.remotePort = req.headers[conf.REMOTE_PORT_HEAD] || 0; req.fromTunnel = oReq.fromTunnel = req.headers[FROM_TUNNEL_HEADER] === '1'; delete req.headers[FROM_TUNNEL_HEADER]; - req.fromComposer = oReq.fromComposer = req.headers[pluginOpts.config.REQ_FROM_HEADER] === 'W2COMPOSER'; + req.fromComposer = oReq.fromComposer = req.headers[conf.REQ_FROM_HEADER] === 'W2COMPOSER'; oReq.servername = oReq.serverName = getValue(req, pluginOpts.SERVER_NAME_HEAD); var certCacheInfo = getValue(req, pluginOpts.CERT_CACHE_INFO); oReq.certCacheName = certCacheInfo; diff --git a/lib/tunnel.js b/lib/tunnel.js index a2c5695bc..d5675dd7b 100644 --- a/lib/tunnel.js +++ b/lib/tunnel.js @@ -75,6 +75,8 @@ function tunnelProxy(server, proxy, type) { var clientInfo = util.parseClientInfo(req); reqSocket.clientIp = req.clientIp = clientInfo[0] || util.getClientIp(req); reqSocket.clientPort = req.clientPort = clientInfo[1] || util.getClientPort(req); + req._remoteAddr = clientInfo[2] || util.getRemoteAddr(req); + req._remotePort = clientInfo[3] || util.getRemotePort(req); delete headers[config.CLIENT_PORT_HEAD]; req.reqId = reqSocket.reqId = util.getReqId(); reqSocket.headers = headers; diff --git a/lib/upgrade.js b/lib/upgrade.js index b1becec0c..017cf3e07 100644 --- a/lib/upgrade.js +++ b/lib/upgrade.js @@ -105,7 +105,7 @@ function upgradeHandler(req, socket) { socket.sniPlugin = req.sniPlugin = sniPlugin; delete headers[config.SNI_PLUGIN_HEADER]; } - socket.isPluginReq = util.checkPluginReqOnce(req); + req.isPluginReq = socket.isPluginReq = util.checkPluginReqOnce(req); util.handleForwardedProps(req); var isHttps = socket.isHttps || req.isHttps || !!headers[config.HTTPS_FIELD]; req.isHttps = socket.isHttps = isHttps; @@ -118,11 +118,13 @@ function upgradeHandler(req, socket) { if (err) { return socket.write(err); } - var clientIp, clientPort; + var clientIp, clientPort, remoteAddr, remotePort; if (isWs) { var clientInfo = util.parseClientInfo(req); clientIp = clientInfo[0] || util.getClientIp(req); clientPort = clientInfo[1] || util.getClientPort(req); + remoteAddr = clientInfo[2] || util.getRemoteAddr(req); + remotePort = clientInfo[3] || util.getRemotePort(req); delete headers[config.CLIENT_PORT_HEAD]; } // 其它协议直接转成普通https请求,方便抓包调试 @@ -136,6 +138,8 @@ function upgradeHandler(req, socket) { req.method = 'GET'; headers[config.CLIENT_IP_HEAD] = clientIp; headers[config.CLIENT_PORT_HEAD] = clientPort; + headers[util.REMOTE_ADDR_HEAD] = remoteAddr; + headers[util.REMOTE_PORT_HEAD] = remotePort; headers[config.PLUGIN_HOOK_NAME_HEADER] = config.PLUGIN_HOOKS.UI; } socket.pause(); diff --git a/lib/util/index.js b/lib/util/index.js index b043ea906..31c0eb697 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -1606,7 +1606,12 @@ function getRemoteAddr(req) { try { var socket = req.socket || req; if (!socket._remoteAddr) { - socket._remoteAddr = removeIPV6Prefix(socket.remoteAddress) || LOCALHOST; + var ip; + if (req.isPluginReq && !req._isProxyReq && req.headers) { + ip = req.headers[config.REMOTE_ADDR_HEAD]; + delete req.headers[config.REMOTE_ADDR_HEAD]; + } + socket._remoteAddr = ip || removeIPV6Prefix(socket.remoteAddress) || LOCALHOST; } return socket._remoteAddr; } catch(e) {} @@ -1626,8 +1631,13 @@ function getRemotePort(req) { try { var socket = req.socket || req; if (socket._remotePort == null) { - var port = socket.remotePort; - socket._remotePort = port > 0 ? port : 0; + var port; + if (req.isPluginReq && !req._isProxyReq && req.headers) { + port = req.headers[config.REMOTE_PORT_HEAD]; + delete req.headers[config.REMOTE_PORT_HEAD]; + } + port = port || socket.remotePort; + socket._remotePort = port > 0 ? port : '0'; } return socket._remotePort; } catch(e) {}