0

我有一个在 SSL 安全服务器上运行的 AngularJS 应用程序。现在我想通过 websocket 联系一个 RaspberryPI 来获取一些流数据。树莓没有自己的网络服务器(nginx/apache),所以我不能使用例如letsencrypt,但只能使用自签名证书。问题是它不起作用,我找不到有效的解决方案(花了 6 小时阅读论坛后)。这是我的代码:

我通过以下方式创建了我的自签名证书:

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

在 AngularJS 中,我做的很简单:

const ip = IPADDRESS:9030
connection = new WebSocket('wss://' + ip);

一个节点服务器正在 Raspberry 上运行。它看起来像这样:

const net = require('net');
const fs = require('fs');
const https = require('https');

var options = {
    key:    fs.readFileSync('ssl/key.pem'),
    cert:   fs.readFileSync('ssl/cert.pem'),
    requestCert: false,
    rejectUnauthorized: false
};

//pass in your express app and credentials to create an https server
const httpsServer = https.createServer(options);
      httpsServer.listen(9030);

/**
 *  server
 */
let connections = {};
let WebSocketServer = require('ws').Server;
let wss = new WebSocketServer({server: httpsServer}),

wss.on('connection', function(ws) {
    ...
}

当启动服务器node server.js并启动我的 AngularJS 应用程序时,我收到错误消息:

WebSocket connection to 'wss://IPADDRESS:9030/' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID

我该怎么做才能让它工作?谢谢你的帮助!

4

1 回答 1

0

好吧,在玩了很多测试之后,它看起来似乎无法使用自签名证书。

我现在使用的最终解决方案是使用 Letsencrypt。以下是步骤。我希望有人会觉得它有用:

首先,您的路由器必须可以通过互联网访问。因此必须打开 HTTP 端口 80 和 HTTPS 端口 443 才能将传入的 TCP 转发到您的 Raspberry。

第 1 步:准备您的 Raspberry 并安装nginx服务器:

sudo apt-get install nginx
sudo /etc/init.d/nginx start

第 2 步:安装 LETSENCRYPT:

cd ~
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

./letsencrypt-auto -d DDNSNAME_ROUTER --redirect -m EMAILADDRESS

在安装过程中,您会被问到一些问题。请记住为 [CN] 输入您的 DNS 名称。

第 3 步:更改一些权限,因为默认情况下文件不可读:

sudu chmod -r 775 /etc/letsencrypt/live
sudu chmod -r 775 /etc/letsencrypt/archive

第 4 步:启用 LETSENCRYPT 自动更新:

./letsencrypt-auto renew
sudo crontab -e

0 0 1 * * /home/pi/letsencrypt/letsencrypt-auto renew

而已!现在您可以wss://在 Angular/AngularJS 应用程序中使用 WebSocket。

能够处理 HTTP 和 HTTPS 请求的节点服务器现在看起来像这样(我的服务器在端口 9030 和 9031 上侦听任何数据。所以请根据您的需要更改它。config.json仅存储一些变量。):

const net = require('net');
const fs = require('fs');
const https = require('https');
const config = require('./server-config.json');

//
//  SSL SERVER
//
try {
    const privateKey = fs.readFileSync('/etc/letsencrypt/live/' + config.DNSROUTERNAME + '/privkey.pem', 'utf8');
    const certificate = fs.readFileSync('/etc/letsencrypt/live/' + config.DNSROUTERNAME + '/cert.pem', 'utf8');
    const ca = fs.readFileSync('/etc/letsencrypt/live/' + config.DNSROUTERNAME + '/chain.pem', 'utf8');

    const options = {
        key: privateKey,
        cert: certificate,
        ca: ca
    };  

    //pass in your express app and credentials to create an https server
    let httpsServer = https.createServer(options);
        httpsServer.listen(9031);
}
catch (e) {
    console.log("LETSENCRYPT certificates not found! HTTPS server not started!");
    console.log(e)
}

/**
 *
 *  server
 *
 */
let connections = {};
let WebSocketServer = require('ws').Server;

// start WS via HTTP
const wss1 = new WebSocketServer({port: 9030});

wss1.on('connection', function(ws) {
    console.log('connection via HTTP');

    ws.on('close', function () {
        console.log('close HTTP!');
    })
})


// start WS via HTTPS
if (typeof httpsServer !== 'undefined') {
    const wss2 = new WebSocketServer({server: httpsServer});

    wss2.on('connection', function(ws) {
        console.log('connection via HTTPS');

        ws.on('close', function () {
            console.log('close HTTPS!');
        })
    })
}

...

我希望这会有所帮助,并且您挽救了一些生命。

PS:请让我知道是否有人找到了无需网络服务器即可使其正常工作的解决方案。我真的不喜欢仅为证书安装网络服务器的方法。

于 2019-02-23T07:03:50.743 回答