Unix socket在HTTPS下似乎不能用,难道是Node的bug?急死了
发布于 7 年前 作者 zhanzhenzhen 4034 次浏览 来自 问答

举个例子,如果服务器绑定在IP地址和端口号上,当然是能运行HTTPS的:

let options = {
    key: fs.readFileSync("key.pem"),
    cert: fs.readFileSync("cert.pem")
};

https.createServer(options, (req, res) => {
    console.log("Request received");
    res.writeHead(200);
    res.end("hello world\n");
}).listen(50000, "127.0.0.1");
console.log("HTTPS server started.");

setTimeout(() => {
    https.request({
        host: "127.0.0.1",
        port: 50000,
        rejectUnauthorized: false
    }).end();
}, 1000);

但一旦绑定的是Unix socket,就不能运行HTTPS了,说self signed certificate error:

let options = {
    key: fs.readFileSync("key.pem"),
    cert: fs.readFileSync("cert.pem")
};

https.createServer(options, (req, res) => {
    console.log("Request received");
    res.writeHead(200);
    res.end("hello world\n");
}).listen("/Users/zzz/test-unix-socket/socket.sock");
console.log("HTTPS server started.");

setTimeout(() => {
    https.request({
        socketPath: "/Users/zzz/test-unix-socket/socket.sock",
        rejectUnauthorized: false
    }).end();
}, 1000);

key.pemcert.pem是用OpenSSL生成的自签名证书:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 7300 -nodes

这难道是Node的bug?

9 回复

没人知道么?急死了

监听文件不是用于外网的,一般是进程间通讯会用。不仅仅nodejs,你换任何语言都一样

如果非要监听文件给外网,至少都要做一层代理,之前的看过有人就是用nginx做反向代理实现了外网对socket文件的监听

@zy445566 Unix socket是可以用于http服务的(也就是说服务器监听的是一个socket文件而不是端口),如果把我上面这个例子中的https改成http,就不会出错了。但我就是不懂为什么https就不行。 详见文档: https://nodejs.org/dist/latest-v6.x/docs/api/http.html#http_server_listen_path_callback

@zhanzhenzhen 666,回去试一下,如果是打脸就认了

@zhanzhenzhen 应该是和你自签的证书有关,证书签发需要域名或者ip的,使用端口模式你指定了ip,和证书的ip对应了,而使用socket@zhanzhenzhen 文件模式的时候没有ip,是不是默认使用了其他的域名或者ip,比如localhost,没有和证书的ip对应?不知道是不是这样?

来自酷炫的 CNodeMD

@zhangmingfeng 是和自签名证书有关,但我不知道证书应该改成什么样,才能不报错。如果真是Node的bug那可比较悲哀了。

@zy445566 我的意思不是“监听外网”,表误解。根据我的理解Unix Socket应该都只能本机访问。

原来真是node的bug,他们刚提交了一个commit。 https://github.com/nodejs/node/issues/13470 @zy445566 @zhangmingfeng 谢谢你们的回复。

你可以用nginx的

server {
	listen 5050;

** ssl on; ssl_certificate ssl/cacert.pem; ssl_certificate_key ssl/privkey.pem;**

	location / {
		proxy_pass http://localhost:3000/;
  		proxy_http_version 1.1;
    	proxy_set_header Upgrade $http_upgrade;
    	proxy_set_header Connection "upgrade";
	}
}
回到顶部