穿过 SNI Proxy,用 SNI 和 ALPN 选择具体服务的 Nodejs 实现方法
穿过 SNI Proxy,用 SNI 和 ALPN 选择具体服务的 Nodejs 实现方法
需要 node 5.0.0 以上. 客户端关键代码大致是这样的:
var clientoptions = {
port: 443,
host: sslhost,
rejectUnauthorized: verifyserver,
ALPNProtocols: alpnproto.split(','),
servername: sslservername,
}
var remote = tls.connect(clientoptions, function() { ... }
相当于 openssl s_client -connect HOST:443 -servername SERVERNAME -alpn ALPNPROTO
这个大家都用上的话那些 Proxy 可能受不了, 所以就不公开服务器端具体做法了.
1 回复
在 Node.js 中,通过 SNI Proxy 并使用 SNI(Server Name Indication)和 ALPN(Application Layer Protocol Negotiation)来选择具体服务,可以利用 tls
模块来实现。以下是一个示例代码,展示了如何根据 SNI 和 ALPN 选择不同的服务:
const tls = require('tls');
const fs = require('fs');
const path = require('path');
// 读取证书和密钥
const options = {
key: fs.readFileSync(path.join(__dirname, 'server-key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'server-cert.pem')),
SNICallback: (servername, cb) => {
const sniOptions = {
servername: servername,
ALPNProtocols: ['h2', 'http/1.1'] // 支持的 ALPN 协议
};
if (servername === 'service1.example.com') {
sniOptions.cert = fs.readFileSync(path.join(__dirname, 'service1-cert.pem'));
} else if (servername === 'service2.example.com') {
sniOptions.cert = fs.readFileSync(path.join(__dirname, 'service2-cert.pem'));
}
cb(null, sniOptions);
}
};
const server = tls.createServer(options, (socket) => {
console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized');
socket.write('welcome!\n');
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.listen(8000, () => {
console.log('server bound');
});
在这个示例中,SNICallback
函数根据 servername
动态加载不同的证书,同时指定支持的 ALPN 协议。当客户端连接到服务器时,它将根据 SNI 和 ALPN 选择合适的证书和协议。确保替换示例中的证书路径和服务器名称为实际使用的值。