我正在尝试设置代理服务器以将向一台服务器发出的请求传递到另一台服务器。我在让它在 HTTPS 上运行时遇到了一些麻烦。
服务器是运行 Windows Server 2019 的虚拟机。
这是我的程序:
const fs = require('fs');
const express = require('express');
const morgan = require('morgan');
const { createProxyMiddleware } = require('http-proxy-middleware');
const Host = '0.0.0.0';
const Port = 3000;
const TargetBaseURL = 'https://myaddressgoeshere.com/';
const sslKey = fs.readFileSync('ssl/key.pem', 'utf8');
const sslCert = fs.readFileSync('ssl/cert.pem', 'utf8');
const app = express();
app.use(morgan('dev'));
app.use('/proxy', createProxyMiddleware({
target: TargetBaseURL,
changeOrigin: true,
pathRewrite: {
[`^/proxy`]: '',
},
protocol: 'https:',
secure: true,
ssl: {
key: sslKey,
cert: sslCert
}
}));
app.listen(Port, Host, () => {
console.log(`Starting Proxy at ${Host}:${Port}`);
});
我通过在命令提示符下执行以下几行创建了自签名证书:
C:
cd "C:\Program Files\Git\usr\bin"
openssl genrsa -out cert.key 2048
openssl req -new -key cert.key -out cert.csr
openssl x509 -req -days 3650 -in cert.csr -signkey cert.key -out cert.crt
openssl x509 -in cert.crt -out cert.pem -outform PEM
openssl rsa -in cert.key -text > key.pem
我将上述步骤创建的文件复制到我的项目
/ssl
文件夹中。
当我向 http://proxyaddress:3000/proxy/login 发出请求时,它会加载但最终失败,因为代理目标的 CSP 需要 https://
当我向 https://proxyaddress:3000/proxy/login 发出请求时,程序永远不会加载,没有请求通过摩根中间件写入控制台,Chrome 会显示一个很好的旧内容:
ERR_SSL_PROTOCOL_ERROR
当我运行curl时,我得到...
curl:(35)LibreSSL / 3.3.6:错误:1404B42E:SSL例程:ST_CONNECT:tlsv1警报协议版本
任何人都可以指出我可以做些什么来让这个工作正常进行吗?
我最终放弃使用 http-proxy-middleware 并改用 express-http-proxy。
这是我的代理的最终工作版本:
const fs = require('fs');
const https = require('https');
const express = require('express');
const morgan = require('morgan');
const expressHttpProxy = require('express-http-proxy');
const config = require('./config.json');
// Settings
const Host = '0.0.0.0';
const Port = config.Port;
const TargetBaseURL = config.TargetBaseURL;
// SSL
const sslKey = fs.readFileSync(__dirname + '/ssl/key.pem', 'utf8');
const sslCert = fs.readFileSync(__dirname + '/ssl/cert.pem', 'utf8');
// Proxy Setup
const proxy = expressHttpProxy(TargetBaseURL, {
https: true,
proxyReqPathResolver: (req) => {
return req.originalUrl;
},
userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
userRes.setHeader('Cache-Control', 'no-store');
let contentType = proxyRes.headers['content-type'];
// Set the content-type
const originalPath = userReq.originalUrl;
if (originalPath.endsWith('.js')) {
contentType = 'application/javascript';
}
else if (originalPath.endsWith('.css')) {
contentType = 'text/css';
}
userRes.setHeader('content-type', contentType);
return proxyResData;
},
});
// Express Server
const app = express();
app.use(morgan('dev'));
app.use('/', proxy);
// Proxy Middleware
const server = https.createServer({
key: sslKey,
cert: sslCert,
timeout: 60000
}, app);
server.listen(Port, Host, () => {
console.log(`Starting Proxy at ${Host}:${Port}`);
});
注意 - 如果您使用此代码 - userResDecorator 部分中的许多行可能会被省略,因为它们特定于我的用例。