node 네트워크 (2)

6487 단어

웹소켓 서비스 구축


웹소켓의 장점:
  • 클라이언트와 서버는 tcp 연결이 하나만 필요합니다
  • 서버를 클라이언트로 푸시할 수 있음
  • 경량화된 프로토콜 헤드, 전송 효율 향상
  • node는 웹소켓의 장점을 사용합니다.
  • WebSocket 클라이언트의 이벤트 기반 프로그래밍 모드는 node의 사용자 정의 이벤트와 유사합니다
  • 웹소켓은 클라이언트와 서버 간의 긴 연결이 필요하고node 이벤트 구동 방식은 양이 많은 클라이언트와 높은 병렬 연결을 유지하는 데 뛰어나다
  • WebSocket 악수


    클라이언트가 업그레이드 프로토콜 요청을 시작합니다.
    GET / chat HTTP / 1.1
    Host: server.example.com
    Upgrade: websocket // websocket
    Connection: Upgrade
    Sec - WebSocket - Key: dGhlIHNhbXBsZSBub25jZQ == 
    Sec - WebSocket - Protocol: chat, superchat // 
    Sec - WebSocket - Version: 13 // 
    
    

    Sec-WebSocket-Key는 보안 검사에 사용되며, 값은 무작위로 생성된 Base64 인코딩 문자열입니다.서버에서 문자열 258EAFA5-E914-47DA-95CA-C5AB0DC85B11과 연결한 다음 sha1로 계산하여 Base64 인코딩하기
    var crypto = require('crypto');
    var val = crypto.createHash('sha1').update(key).digest('base64');
    
    // b 
    HTTP / 1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade 
    Sec - WebSocket - Accept: s3pPLMBiTxaQ9kYGzzhZRbK + xOo =
    Sec - WebSocket - Protocol: chat
    
    

    클라이언트가 Sec-WebSocket-Accept를 검증하고 정확하면 데이터 전송을 시작합니다.

    WebSocket 데이터 전송


    악수 후 웹소켓 데이터 프레임 프로토콜을 시작합니다. 악수 완료 클라이언트 onopen () 트리거
    socket.onopen = function() { 
      // TODO: opened()
    };
    
    

    서버는 onopen () 방법이 없습니다. tcp 플러그인 이벤트를 웹소켓 이벤트로 봉인하려면 데이터를 수발할 때 처리해야 합니다. 웹소켓의 데이터 프레임은 베이스 데이터 이벤트에 봉인됩니다.
    // 
    WebSocket.prototype.setSocket = function(socket) {
       this.socket = socket;
       this.socket.on('data', this.receiver);
    };
    
    // 
    WebSocket.prototype.send = function(data) {
       this._send(data);
    };
    
    

    한쪽은send () 를 호출하여 발송할 때, 다른 한쪽은onmessage를 터치하고, 프로토콜은 데이터를 다중 프레임으로 봉인해서 발송할 수 있습니다.클라이언트는 전송된 데이터 프레임에 대해 마스크 처리를 해야 합니다. 서버가 마스크 없는 프레임을 받으면 연결이 끊어지고 서버가 전송할 때 필요하지 않습니다.websocket
    Smaller icon
  • fin 만약 이 데이터 프레임이 마지막 프레임일 때 1(데이터가 한 프레임이면 그것도 1)이고 나머지는 0
  • rsv1,rsv2,rsv3:1의 길이는 표지 확장에 사용되며, 확장이 있을 때 1
  • opcode: 4비트(0~15) 0: 추가 데이터 프레임, 1: 텍스트 데이터 프레임, 2: 이진 데이터 프레임, 8: 연결 닫기 프레임, 9:ping 데이터 프레임, 10:pong 데이터 프레임 ping, pong은 심장 박동 측정에 사용되며, 한쪽은ping, 한쪽은pong
  • masked 마스크 처리 클라이언트 발송 여부 1 서버 0
  • payload 표지 데이터 길이
  • masking key 마스크가 1일 때 길이 32비트가 복호화
  • payload 데이터 목표 데이터 비트 8의 배수
  • 네트워크 서비스 및 보안

  • ssl(Secure Sockets Layer, 보안 커버 레이어), 전송 레이어에 적용
  • TLS(Transport Layer Security, Security Transport Layer Protocol), IETF 표준화
  • node는crypto,tls,https를 제공합니다.crypto는 복호화에 사용됩니다. tls는 net 기능과 유사합니다. 차이점은 TLS/SSL 암호화된 tcp에 세워진 것입니다.https와 http 인터페이스도 일치하고 안전한 연결에 대한 차이점도 있다

    TLS/SSL

  • 비대칭 암호화, 데이터 전송을 위한 공개 키, 개인 키 복호화
  • Smaller icon
    node의 tls/ssl은 openssl로 이루어진 것으로 공공, 개인 키로 참조를 생성합니다.
    //   
    $ openssl genrsa -out server.key 1024 //   
    $ openssl genrsa -out client.key 1024
    
    // 1024 RSA 
    $ openssl rsa -in server.key -pubout -out server.pem
    $ openssl rsa -in client.key -pubout -out client.pem
    
    

    디지털 인증서
  • CA 인증 및 검증 제공
  • 브로커 공격 방지
  • : 서버와 클라이언트가 키를 교환할 때 그 중 한 측으로 위장하여 공공 키를 보내고 클라이언트에 대해 서버로 위장한다.그래서 공개 키 인증이 필요합니다. 대상 서버에서 온 것을 확인해야 합니다.
    서비스 측은 개인 키를 통해 CSR(Certificate Signing Request, 인증서 서명 요청)을 생성하고,ca는 이 서버에 속하는 서명 인증서를 발급합니다
    자체 서명 인증서 프로세스:
    \\ca ,csr , 
    $ openssl genrsa -out ca.key 1024
    $ openssl req -new -key ca.key -out ca.csr
    $ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
    \\ csr, ca , 
    $ openssl req -new -key server.key -out server.csr
    $ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
    
    

    클라이언트가 보안 연결을 시작하면 서버 인증서를 가져와ca의 인증서로 서버 인증서를 검증합니다. 진위, 서버 이름, IP 등을 포함합니다.유명한ca의 인증서는 일반적으로 브라우저에 미리 설치되어 있으며, 서명한ca는 클라이언트가 설치해야 검증할 수 있습니다

    tcl 서비스 만들기

  • node의 tls를 통해 안전한 tcp 서비스 만들기
  • // 
    var tls = require('tls');
    var fs = require('fs');
    var options = {
        key: fs.readFileSync('./keys/server.key'),
        cert: fs.readFileSync('./keys/server.crt'),
        requestCert: true,
        ca: [fs.readFileSync('./keys/ca.crt')]
    };
    var server = tls.createServer(options, function(stream) {
        console.log('server connected', stream.authorized ? 'authorized' : 'unauthorized');
        stream.write("welcome!
    "); stream.setEncoding('utf8'); stream.pipe(stream); }); server.listen(8000, function() { console.log('server bound'); }); // : $ openssl s_client -connect 127.0.0.1:8000 // $ openssl genrsa - out client.key 1024 $ openssl req - new - key client.key - out client.csr $ openssl x509 - req - CA ca.crt - CAkey ca.key - CAcreateserial - in client.csr - out client.crt var fs = require('fs'); var tls = require('tls'); var options = { key: fs.readFileSync('./keys/client.key'), cert: fs.readFileSync('./keys/client.crt'), ca: [fs.readFileSync('./keys/ca.crt')] }; var stream = tls.connect(8000, options, function() { console.log('client connected', stream.authorized ? 'authorized' : 'unauthorized'); process.stdin.pipe(stream); }); stream.setEncoding('utf8'); stream.on('data', function(data) { console.log(data); }); stream.on('end', function() { server.close(); }); // tcp

    https 서비스

  • node의 https를 사용하여 http보다 하나의 설정
  • var https = require('https');
    var fs = require('fs');
    var options = {
        key: fs.readFileSync('./keys/server.key'),
        cert: fs.readFileSync('./keys/server.crt')
    };
    https.createServer(options, function(req, res) {
        res.writeHead(200);
        res.end("hello world
    "); }).listen(8000); // $ curl https://localhost:8000/ -k, -carcert ca // var https = require('https'); var fs = require('fs'); var options = { hostname: 'localhost', port: 8000, path: '/', method: 'GET', key: fs.readFileSync('./keys/client.key'), cert: fs.readFileSync('./keys/client.crt'), ca: [fs.readFileSync('./keys/ca.crt')] }; options.agent = new https.Agent(options);//https var req = https.request(options, function(res) { res.setEncoding('utf-8'); res.on('data', function(d) { console.log(d); }); }); req.end(); req.on('error', function(e) { console.log(e); });

    좋은 웹페이지 즐겨찾기