SSL के साथ n.js, socket.io


163

मैं अपने SSL प्रमाणपत्र के साथ socket.io चलाने की कोशिश कर रहा हूं, हालांकि, यह कनेक्ट नहीं होगा।

मैंने चैट कोड से अपना कोड आधारित किया है:

var https = require('https');
var fs = require('fs');
/**
 * Bootstrap app.
 */
var sys = require('sys')
require.paths.unshift(__dirname + '/../../lib/');

/**
* Module dependencies.
*/

var express = require('express')
  , stylus = require('stylus')
  , nib = require('nib')
  , sio = require('socket.io');

/**
 * App.
 */
var privateKey = fs.readFileSync('../key').toString();
var certificate = fs.readFileSync('../crt').toString();
var ca = fs.readFileSync('../intermediate.crt').toString();

var app = express.createServer({key:privateKey,cert:certificate,ca:ca });


/**
 * App configuration.
 */

...

/**
 * App routes.
 */

app.get('/', function (req, res) {
  res.render('index', { layout: false });
});

/**
 * App listen.
 */

app.listen(443, function () {
  var addr = app.address();
  console.log('   app listening on http://' + addr.address + ':' + addr.port);
});

/**
 * Socket.IO server (single process only)
 */

var io = sio.listen(app,{key:privateKey,cert:certificate,ca:ca});
...

यदि मैं SSL कोड हटाता हूं तो यह ठीक चलता है, हालांकि इसके साथ मुझे http://domain.com/socket.io/1/?t=1309967919512 पर एक अनुरोध प्राप्त होता है

ध्यान दें कि यह https की कोशिश नहीं कर रहा है, जिसके कारण यह विफल हो जाता है।

मैं क्रोम पर परीक्षण कर रहा हूं, क्योंकि यह इस एप्लिकेशन का लक्ष्य ब्राउज़र है।

मैं माफी माँगता हूँ अगर यह एक आसान सवाल है, तो मैं एक नोड / सॉकेट हूँ।

धन्यवाद!


क्या आपका क्लाइंट ss wss: // ’से पहले के यूआरआई से जुड़ने की कोशिश कर रहा है।
कनक जूल

नहीं, यह वहाँ नहीं मिलता है, यह domain.com/socket.io/1/?t=1309967919512 पर अनुरोध करता है फिर मर जाता है।
से परे

आप कनेक्ट करने के लिए पते को कैसे निर्दिष्ट कर रहे हैं? "domain.com" सॉकेट में एक प्लेसहोल्डर की तरह लगता है। क्लाइंट-साइड लाइब्रेरी। क्या आप अपने क्लाइंट जावास्क्रिप्ट कोड को पोस्ट कर सकते हैं जिसे आप कनेक्ट करने के लिए उपयोग कर रहे हैं?
कनक

1
परियोजना GitHub पर है: github.com/BCCasino/BCCasino
परे

मूल रूप से अपने नोड.जेएस सॉकेट को हटा दें। यह जादुई रूप से क्लाइंट साइड सामान को संभालता है, आप सभी को सॉकेट चलाते हैं। कनेक्ट
परे

जवाबों:


186

अपने प्रारंभिक कनेक्शन के लिए एक सुरक्षित URL का उपयोग करें, अर्थात "http: //" के बजाय "https: //" का उपयोग करें। यदि WebSocket ट्रांसपोर्ट को चुना जाता है, तो Socket.IO को WebSocket के लिए भी स्वचालित रूप से "wss: //" (SSL) का उपयोग करना चाहिए।

अपडेट :

आप 'सुरक्षित' विकल्प का उपयोग करके कनेक्शन बनाने का भी प्रयास कर सकते हैं:

var socket = io.connect('https://localhost', {secure: true});

हम यह करते हैं। हम गोटो https: // www.thebitcoinwheel.com और यह अभी भी स्वचालित रूप से http के लिए एक अनुरोध करता है, यह सॉकेट.आईओ कोड के साथ कुछ है और सवाल का बिंदु है।
आगे

1
आप लोगों ने मेरी जान बचाई! मैं प्रलेखन पर उन विकल्पों को नहीं खोज सका।
पाउलो सेसर

14
{secure: true}यदि आपको url में 'https' निर्दिष्ट नहीं करना चाहिए। यहाँ socket.io ग्राहक स्रोत secure: 'https' == uri.protocol(संस्करण 0.9.16) से एक अंश है , यह सही विकल्प को सेट करता है यदि url में https का पता लगाया जाता है।
जिओचुआन यू जूल

4
मैंने https URL के साथ यह कोशिश की और वास्तव {secure: true}में सही ढंग से काम करने की आवश्यकता नहीं थी।
D Coetzee

4
मेरा मानना ​​है कि यह आश्वस्त करना उचित होगा कि कनेक्शन सुरक्षित दोनों का उपयोग करके सुरक्षित है: सच और क्लाइंट पक्ष को https url जारी करना। इस तरह कोई फर्क नहीं पड़ता कि आप जानते हैं कि यह एक सुरक्षित कनेक्शन होगा।
गबियो

53

इस तरह मैंने इसे एक्सप्रेस के साथ स्थापित करने में कामयाबी हासिल की:

var fs = require( 'fs' );
var app = require('express')();
var https        = require('https');
var server = https.createServer({
    key: fs.readFileSync('./test_key.key'),
    cert: fs.readFileSync('./test_cert.crt'),
    ca: fs.readFileSync('./test_ca.crt'),
    requestCert: false,
    rejectUnauthorized: false
},app);
server.listen(8080);

var io = require('socket.io').listen(server);

io.sockets.on('connection',function (socket) {
    ...
});

app.get("/", function(request, response){
    ...
})


मुझे उम्मीद है कि इससे किसी का समय बचेगा।

अपडेट: उपयोग करने वालों के लिए एन्क्रिप्ट का उपयोग करने देता है

var server = https.createServer({ 
                key: fs.readFileSync('privkey.pem'),
                cert: fs.readFileSync('fullchain.pem') 
             },app);

2
यह एकमात्र समाधान है जिसने मेरे लिए काम किया। मेरा समय बचाने के लिए धन्यवाद।
फ्रांसिस्को हॉज

थोड़ा सा परीक्षण और त्रुटि के बाद मेरे लिए अच्छा काम किया
RozzA

3
इस समाधान ने मेरे लिए एकदम सही काम किया, धन्यवाद। यदि आप letencrypt.org से फ्री सेरट्स का उपयोग कर रहे हैं तो आप निम्न कोड का उपयोग कर सकते हैं .. var server = https.createServer({ key: fs.readFileSync('/etc/letsencrypt/live/domain.name/privkey.pem'), cert: fs.readFileSync('/etc/letsencrypt/live/domain.name/cert.pem'), ca: fs.readFileSync('/etc/letsencrypt/live/domain.name/chain.pem'), requestCert: false, rejectUnauthorized: false },app); server.listen(3000);
ह्यूगो रूण

2
इस उत्तर के लिए बहुत बहुत धन्यवाद। इससे मुझे बहुत मदद मिली है।
हर्ष जस्सी

2
धन्यवाद, letencrypt और .pem फ़ाइलों के साथ एक आकर्षण की तरह काम किया
एरिक

33

एक ही नोट पर, यदि आपका सर्वर दोनों का समर्थन करता है httpऔर httpsआप का उपयोग कर कनेक्ट कर सकते हैं:

var socket = io.connect('//localhost');

करने के लिए स्वत: ब्राउज़र योजना का पता लगाने और HTTP / HTTPS तदनुसार का उपयोग कर कनेक्ट। जब https में, ट्रांसपोर्ट को डिफ़ॉल्ट रूप से सुरक्षित किया जाएगा, जैसे कि कनेक्टिंग का उपयोग करके

var socket = io.connect('https://localhost');

सुरक्षित वेब सॉकेट का उपयोग करेगा - wss://( {secure: true}बेमानी है)।

एक ही नोड सर्वर का उपयोग करके आसानी से http और https दोनों की सेवा के बारे में अधिक जानकारी के लिए इस उत्तर को देखें


10

यदि आपके सर्वर प्रमाणित फ़ाइल पर भरोसा नहीं किया गया है, (उदाहरण के लिए, आप जावा में keytool कमांड के साथ खुद के द्वारा कीस्टोर उत्पन्न कर सकते हैं ), आपको अतिरिक्त विकल्प जोड़ना चाहिए अस्वीकृत

var socket = io.connect('https://localhost', {rejectUnauthorized: false});

सराहना की जाएगी यदि आपने एक उदाहरण जोड़कर बताया कि आपने नोड के लिए उस कुंजी को बनाने के लिए कैसे कुंजी का उपयोग किया था। 'कारण कुंजियाँ इतनी जटिल हैं और इसके बारे में पर्याप्त ट्यूटोरियल नहीं हैं।
bvdb

keytool जावा डेवलपमेंट किट (JDK) के अंदर एक टूल है। आप इस docs.oracle.com/javase/10/tools/…
क्लैरटेंशन

4

check.configuration ..

app = module.exports = express();
var httpsOptions = { key: fs.readFileSync('certificates/server.key'), cert: fs.readFileSync('certificates/final.crt') };        
var secureServer = require('https').createServer(httpsOptions, app);
io = module.exports = require('socket.io').listen(secureServer,{pingTimeout: 7000, pingInterval: 10000});
io.set("transports", ["xhr-polling","websocket","polling", "htmlfile"]);
secureServer.listen(3000);

2

सर्वर साइड:

import http from 'http';
import https from 'https';
import SocketIO, { Socket } from 'socket.io';
import fs from 'fs';
import path from 'path';

import { logger } from '../../utils';

const port: number = 3001;

const server: https.Server = https.createServer(
  {
    cert: fs.readFileSync(path.resolve(__dirname, '../../../ssl/cert.pem')),
    key: fs.readFileSync(path.resolve(__dirname, '../../../ssl/key.pem'))
  },
  (req: http.IncomingMessage, res: http.ServerResponse) => {
    logger.info(`request.url: ${req.url}`);

    let filePath = '.' + req.url;
    if (filePath === './') {
      filePath = path.resolve(__dirname, './index.html');
    }

    const extname = String(path.extname(filePath)).toLowerCase();
    const mimeTypes = {
      '.html': 'text/html',
      '.js': 'text/javascript',
      '.json': 'application/json'
    };

    const contentType = mimeTypes[extname] || 'application/octet-stream';

    fs.readFile(filePath, (error: NodeJS.ErrnoException, content: Buffer) => {
      if (error) {
        res.writeHead(500);
        return res.end(error.message);
      }
      res.writeHead(200, { 'Content-Type': contentType });
      res.end(content, 'utf-8');
    });
  }
);

const io: SocketIO.Server = SocketIO(server);

io.on('connection', (socket: Socket) => {
  socket.emit('news', { hello: 'world' });
  socket.on('updateTemplate', data => {
    logger.info(data);
    socket.emit('updateTemplate', { random: data });
  });
});

server.listen(port, () => {
  logger.info(`Https server is listening on https://localhost:${port}`);
});

ग्राहक की ओर:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Websocket Secure Connection</title>
</head>

<body>
  <div>
    <button id='btn'>Send Message</button>
    <ul id='messages'></ul>
  </div>
  <script src='../../../node_modules/socket.io-client/dist/socket.io.js'></script>
  <script>
    window.onload = function onload() {
      const socket = io('https://localhost:3001');
      socket.on('news', function (data) {
        console.log(data);
      });

      socket.on('updateTemplate', function onUpdateTemplate(data) {
        console.log(data)
        createMessage(JSON.stringify(data));
      });
      const $btn = document.getElementById('btn');
      const $messages = document.getElementById('messages');

      function sendMessage() {
        socket.emit('updateTemplate', Math.random());
      }

      function createMessage(msg) {
        const $li = document.createElement('li');
        $li.textContent = msg;
        $messages.appendChild($li);
      }

      $btn.addEventListener('click', sendMessage);
    }
  </script>
</body>

</html>

2

अपनी आवश्यकताओं के आधार पर, आप सुरक्षित और असुरक्षित दोनों तरह के कनेक्शन की अनुमति दे सकते हैं और फिर भी केवल एक सॉकेट का उपयोग कर सकते हैं।

आपको बस दो सर्वर, एक HTTP के लिए और एक HTTPS के लिए देना होगा, फिर उन सर्वरों को Socket.io उदाहरण में संलग्न करें।

सर्वर साइड :

// needed to read certificates from disk
const fs          = require( "fs"    );

// Servers with and without SSL
const http        = require( "http"  )
const https       = require( "https" );
const httpPort    = 3333;
const httpsPort   = 3334;
const httpServer  = http.createServer();
const httpsServer = https.createServer({
    "key" : fs.readFileSync( "yourcert.key" ),
    "cert": fs.readFileSync( "yourcert.crt" ),
    "ca"  : fs.readFileSync( "yourca.crt"   )
});
httpServer.listen( httpPort, function() {
    console.log(  `Listening HTTP on ${httpPort}` );
});
httpsServer.listen( httpsPort, function() {
    console.log(  `Listening HTTPS on ${httpsPort}` );
});

// Socket.io
const ioServer = require( "socket.io" );
const io       = new ioServer();
io.attach( httpServer );
io.attach( httpsServer );

io.on( "connection", function( socket ) {

    console.log( "user connected" );
    // ... your code

});

ग्राहक की ओर :

var url    = "//example.com:" + ( window.location.protocol == "https:" ? "3334" : "3333" );
var socket = io( url, {
    // set to false only if you use self-signed certificate !
    "rejectUnauthorized": true
});
socket.on( "connect", function( e ) {
    console.log( "connect", e );
});

यदि आपका NodeJS सर्वर आपके वेब सर्वर से अलग है, तो आपको शायद कुछ CORS हेडर सेट करने होंगे। तो सर्वर साइड में, बदलें:

httpServer.listen( httpPort, function() {
    console.log(  `Listening HTTP on ${httpPort}` );
});
httpsServer.listen( httpsPort, function() {
    console.log(  `Listening HTTPS on ${httpsPort}` );
});

साथ में:

const httpServer  = http.createServer( (req, res) => {
    res.setHeader( "Access-Control-Allow-Origin"  , "*" );
    res.setHeader( "Access-Control-Request-Method", "*" );
    res.setHeader( "Access-Control-Allow-Methods" , "*" );
    res.setHeader( "Access-Control-Allow-Headers" , "*" );
    if ( req.method === "OPTIONS" ) {
        res.writeHead(200);
        res.end();
        return;
    }
});
const httpsServer = https.createServer({
        "key" : fs.readFileSync( "yourcert.key" ),
        "cert": fs.readFileSync( "yourcert.crt" )
    }, (req, res) => {
    res.setHeader( "Access-Control-Allow-Origin"  , "*" );
    res.setHeader( "Access-Control-Request-Method", "*" );
    res.setHeader( "Access-Control-Allow-Methods" , "*" );
    res.setHeader( "Access-Control-Allow-Headers" , "*" );
    if ( req.method === "OPTIONS" ) {
        res.writeHead(200);
        res.end();
        return;
    }
});

और निश्चित रूप से अपनी आवश्यकताओं के अनुसार हेडर के मूल्यों को समायोजित करें।


1

एंटरप्राइज़ एप्लिकेशन के लिए यह ध्यान दिया जाना चाहिए कि आपको अपने कोड में https नहीं संभालना चाहिए। इसे IIS या nginx के माध्यम से स्वतः अपग्रेड किया जाना चाहिए। एप्लिकेशन को इस बारे में नहीं पता होना चाहिए कि प्रोटोकॉल का क्या उपयोग किया जाता है।


0

यह मेरी nginx config फाइल और iosocket कोड है। सर्वर (एक्सप्रेस) पोर्ट 9191 पर सुन रहा है। यह अच्छी तरह से काम करता है: nginx config फाइल:

server {
    listen       443 ssl;
    server_name  localhost;
    root   /usr/share/nginx/html/rdist;

    location /user/ {
        proxy_pass   http://localhost:9191;
    }
    location /api/ {
        proxy_pass   http://localhost:9191;
    }
    location /auth/ {
        proxy_pass   http://localhost:9191;
    }

    location / {
        index  index.html index.htm;
        if (!-e $request_filename){
          rewrite ^(.*)$ /index.html break;
        }
    }
    location /socket.io/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass   http://localhost:9191/socket.io/;
    }


    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    ssl_certificate /etc/nginx/conf.d/sslcert/xxx.pem;
    ssl_certificate_key /etc/nginx/conf.d/sslcert/xxx.key;

}

सर्वर:

const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection', (socket) => {
    handleUserConnect(socket)

  socket.on("disconnect", () => {
   handleUserDisConnect(socket)
  });
})

server.listen(9191, function () {
  console.log('Server listening on port 9191')
})

क्लाइंट (प्रतिक्रिया):

    const socket = io.connect('', { secure: true, query: `userId=${this.props.user._id}` })

        socket.on('notifications', data => {
            console.log('Get messages from back end:', data)
            this.props.mergeNotifications(data)
        })
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.