穿过 SNI Proxy,用 SNI 和 ALPN 选择具体服务的 Nodejs 实现方法

发布于 1周前 作者 sinazl 来自 nodejs/Nestjs

穿过 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 选择合适的证书和协议。确保替换示例中的证书路径和服务器名称为实际使用的值。

回到顶部