2012-08-31 21 views
23

Chcę dynamicznie zwracać informacje o certyfikatach ssl w mojej aplikacji NodeJS. Mam dwie nazwy domen połączone z tą samą aplikacją węzła. Widzę tylko, że ustawienia ssl można określić podczas tworzenia serwera. Czy możliwe jest dynamiczne zwracanie certyfikatów ssl na podstawie żądanego adresu URL?Czy jest możliwe dynamiczne zwrócenie certyfikatu SSL w NodeJS?

W przeciwnym razie, jeśli muszę zamiast tego utworzyć drugą instancję serwera na innym porcie, czy będę w stanie przezroczyście przesyłać każde żądanie do oryginalnego portu? Czy mogę sprawić, żeby wyglądało, jakby nie działał na drugim porcie?

Dzięki Jeff

+1

Chciałbym odpowiedzi na to również. Planuję zbudować aplikację Node.js, która może obsługiwać wiele domen z certyfikatem SSL dla każdego. Byłoby użyteczne, gdybyśmy mogli przechowywać informacje o certyfikatach SSL w bazie danych. Gdy wykryjemy domenę, z której pochodzą, możemy wyświetlić ich tematykę i treść. Wiem, że Node.js ma sposób zdefiniowania certyfikatu SSL na czas uruchamiania, ale nie zna sposobu, aby zrobić to dynamicznie w oparciu o domenę, na której się znajdują. – Keverw

+1

nie jestem pewien, ale czy https://github.com/nodejitsu/node-http-proxy nie byłoby pomocne? –

Odpowiedz

41

Tak, to jest możliwe, aby to zrobić z jednego serwera. Ale zastrzeżenie jest takie, że działa na klientach obsługujących SNI - co jest najnowocześniejszą przeglądarką.

ten sposób można to zrobić:

//function to pick out the key + certs dynamically based on the domain name 
function getSecureContext (domain) { 
    return crypto.createCredentials({ 
     key: fs.readFileSync('/path/to/domain.key'), 
     cert: fs.readFileSync('/path/to/domain.crt'), 
     ca: [fs.readFileSync('/path/to/CA_cert_1.crt'), fs.readFileSync('/path/to/CA_cert_2.crt'), <include all CA certs that you have to> ... ] 
     }).context; 
} 

//read them into memory 
var secureContext = { 
    'domain1': getSecureContext('domain1'), 
    'domain2': getSecureContext('domain2'), 
    . 
    . 
} 

//provide a SNICallback when you create the options for the https server 
var options = { 
    SNICallback: function (domain) { 
     return secureContext[domain]; 
    }, //SNICallback is passed the domain name, see NodeJS docs on TLS 
    cert: fs.readFileSync('/path/to/server.crt'), 
    key: fs.readFileSync('/path/to/server.key'),     
    } 
} 

//create your https server 
var server = require('https').createServer(options, [requestListener]); 
//using Express 
var server = require('https').createServer(options, require('express')()); 
server.listen(<someport>); 

To działa, ponieważ the options for https jest podobna do tls.createServer(). Upewnij się, że do certyfikatu crypto.createCredentials są dołączone wszystkie wymagane certyfikaty pośrednie i główne. Jeśli masz pakiet CA, podziel je na wiele plików CRT, zanim użyjesz ich jako "ca" akceptuje tablicę certyfikatów.

+0

Nice! Czy każdy certyfikat SSL będzie wymagał dedykowanego adresu IP? Chcę hostować wiele domen z SSL na tym samym serwerze. Jeśli kupimy ich witrynę, automatycznie kupimy dla nich certyfikat SSL i domenę za pomocą interfejsu API. Gdybym mógł uruchomić wiele domen na tym samym serwerze z tym samym adresem IP, byłoby świetnie, ale mam wrażenie, że każdy certyfikat będzie wymagał dedykowanego adresu IP, ale nie jest zbyt pewny. – Keverw

+0

i chciałbym być dostępny do dynamicznego usuwania/dodawania stron internetowych. Budowanie aplikacji SaaS lub przynajmniej takiej i tej części byłoby czymś, czego potrzebujemy wcześnie. Po przeczytaniu tej strony wikipedii wygląda na to, że nie potrzebujemy dedykowanego adresu IP. Więc to jest plus, ale czy getSecureContext jest wywoływany w czasie żądania lub po uruchomieniu serwera? Ponieważ getSecureContext może następnie wyszukiwać w bazie danych za każdym razem, gdy witryna otrzymuje żądanie certyfikatu SSL. hmm.Próbując zastanowić się, jak to powinno działać. – Keverw

+0

i zastanawiam się, co zrobi w starszych przeglądarkach, które go nie obsługują. Daj im błędy certyfikatów, które zakładam? – Keverw

15

crypto.createCredentials() jest przestarzałe, więc użyj zamiast niego tls.createSecureContext().

tls.createServer() musi mieć w opcjach key i cert, ponieważ są one wymagane w instrukcji. Być może tls.createServer() używa tych parametrów jako domyślnych w przypadku, gdy SNICallback nie jest obsługiwane.

var secureContext = { 
    'mydomain.com': tls.createSecureContext({ 
     key: fs.readFileSync('../path_to_key1.pem', 'utf8'), 
     cert: fs.readFileSync('../path_to_cert1.crt', 'utf8'), 
     ca: fs.readFileSync('../path_to_certificate_authority_bundle.ca-bundle1', 'utf8'), // this ca property is optional 
    }), 
    'myotherdomain.com': tls.createSecureContext({ 
     key: fs.readFileSync('../path_to_key2.pem', 'utf8'), 
     cert: fs.readFileSync('../path_to_cert2.crt', 'utf8'), 
     ca: fs.readFileSync('../path_to_certificate_authority_bundle.ca-bundle2', 'utf8'), // this ca property is optional 
    }), 
} 
try { 
    var options = { 
     SNICallback: function (domain, cb) { 
      if (secureContext[domain]) { 
       if (cb) { 
        cb(null, secureContext[domain]); 
       } else { 
        // compatibility for older versions of node 
        return secureContext[domain]; 
       } 
      } else { 
       throw new Error('No keys/certificates for domain requested'); 
      } 
     }, 
     // must list a default key and cert because required by tls.createServer() 
     key: fs.readFileSync('../path_to_key.pem'), 
     cert: fs.readFileSync('../path_to_cert.crt'), 
    } 
    https.createServer(options, function (req, res) { 
     res.end('Your dynamic SSL server worked!') 
     // Here you can put proxy server routing here to send the request 
     // to the application of your choosing, running on another port. 
     // node-http-proxy is a great npm package for this 
    }).listen(443); 
} catch (err){ 
    console.error(err.message); 
    console.error(err.stack); 
} 

Wewnątrz serwera można użyć nodejs pakiet http-proxy na trasie twoi https żądania do różnych zastosowań.

-1

Chciałem tylko podkreślić, że @clusterfork był idealny dla mnie, ale aktualizacja systemu spowodowała awarię całego rozwiązania, ponieważ teraz SNICallback działa z 2 parametrami, a prosta aktualizacja systemu spowodowała, że ​​wszystko nagle się zawiesiło. Teraz znów działa, ponieważ SNICallback ma teraz 2 parametry, wywołania zwrotne domeny & i prosta adaptacja kodu sprawiła, że ​​działa, jak @risyasin powiedział to w komentarzach.

Powiązane problemy