Tidak dapat memverifikasi tanda tangan daun

142

Saya menggunakan node.js request.js untuk mencapai api. Saya mendapatkan kesalahan ini

[Kesalahan: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Semua kredensial saya akurat dan valid, dan server baik-baik saja. Saya membuat permintaan yang sama dengan tukang pos.

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Kode ini hanya berjalan di ex skrip yang dapat dieksekusi. node ./run_file.jsApakah itu sebabnya? Apakah perlu dijalankan di server?

ThomasReggi
sumber
Ini kemungkinan besar, tetapi mungkinkah API tidak mengenali agen pengguna yang dilewatkan oleh program simpul Anda?
Hector Correa
1
Hum ... juga lihat ini: blog.gaeremynck.com/fixing-unable_to_verify_leaf_signature
Hector Correa
@HectorCorrea Saya bisa membaca api di tukang pos dengan sempurna. Mengapa simpul tidak bisa melakukannya? Saya mencoba mengubah agen pengguna, tidak berhasil.
ThomasReggi

Jawaban:

157

Catatan : berikut ini berbahaya, dan akan memungkinkan konten API dicegat dan dimodifikasi antara klien dan server.

Ini juga berhasil

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

ThomasReggi
sumber
22
Saya memperbarui ini, dan terima kasih telah menjawab, tetapi ini secara aktif merusak keamanan Anda. Anda harus menambahkan CA yang hilang per @ CoolAJ86 jawaban di bawah ini.
mikemaccana
4
Saya menggunakan plugin NodeJS yang dipanggil nodemailerdan nodemailer-smtp-transportdan perintah umum yang sama berhasil. Anda perlu menambahkan ini ke createTransportobjek Anda :tls:{rejectUnauthorized: false}
LukeP
3
@ LukeP sama-sama tidak aman dengan nodemailer kurasa. Ada petunjuk dalam nama: jika ada sesuatu yang Un resmi, biasanya Anda ingin menolaknya, dengan definisi. Yang Anda butuhkan adalah menemukan cara untuk mengotorisasi dengan benar (dengan mengatur sertifikat CA dengan benar, seperti jawaban lain sudah katakan).
Bruno
@ Bruno Saya setuju, Anda harus mengaturnya dengan benar dengan sertifikat. Saya hanya ingin menyiapkan tes cepat untuk demo sehingga kode yang saya posting adalah perbaikan cepat. Seharusnya saya memulainya dengan komentar saya.
LukeP
1
@mikemaccana Tidak ada masalah keamanan jika permintaan ada di server yang sama dan Anda adalah satu-satunya pemilik.
Binar Web
89

Ini bukan masalah dengan aplikasi, tetapi dengan sertifikat yang ditandatangani oleh perantara CA. Jika Anda menerima fakta itu dan masih ingin melanjutkan, tambahkan berikut ini untuk meminta opsi:

rejectUnauthorized: false

Permintaan penuh:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});
Andrei Karpushonak
sumber
Saya memiliki masalah ini sekarang di tempat kerja. Saya mengirimkan tiket TI yang memberi tahu mereka bahwa SSL mungkin tidak terkonfigurasi - mereka memberi tahu saya bahwa saya sangat membutuhkan. Apakah ada informasi lain yang bisa saya berikan kepada mereka untuk menyelesaikan masalah ini?
blakev
Ini sebenarnya tidak benar: seperti CoolAJ86 dan hectorcorrea menyebutkan, sertifikat itu valid, tetapi ditandatangani oleh perantara CA.
mikemaccana
80

Solusi Aman

Daripada mematikan keamanan, Anda dapat menambahkan sertifikat yang diperlukan ke rantai. Pertama instal paket ssl-root-cas dari npm:

npm install ssl-root-cas

Paket ini berisi banyak sertifikat perantara yang dipercayai peramban tetapi simpul tidak.

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

Akan menambah sertifikat yang hilang. Lihat di sini untuk info lebih lanjut:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

Juga, Lihat jawaban berikutnya di bawah ini

coolaj86
sumber
2
Apakah klien Http tidak menggunakan toko sertifikat Otoritas Sertifikasi Tepercaya Windows Tepercaya?
Richard Collette
1
simpul menggunakan sertifikat mozilla yang dibundel dalam biner dan menimpanya setiap kali Anda menyediakan caarray Anda sendiri . Saya tidak tahu apakah modul http-nya juga akan melihat ke rantai OS. Namun, curl pada OS X tampaknya hanya menggunakan rantai OS dan tidak mengizinkan sertifikat yang ditentukan secara manual.
coolaj86
Apakah ini harus dijalankan untuk setiap proses atau dapatkah saya menjalankannya sekali dan memperbarui sertifikat saya secara global?
Joshua Snider
Sertifikat disimpan di dua tempat yang berpotensi: (1) built-in ke node.js binary (2) keystore sistem operasi. Jika sertifikat Anda kedaluwarsa, Anda harus memasukkan ini ke dalam kode Anda yang sedang berjalan. Itu tidak mengubah simpul biner atau sistem operasi Anda - hanya folder proyek.
coolaj86
1
@ Sunkas Persis seperti yang dikatakan pesan kesalahan. Saya tidak tahu bagaimana menjelaskannya dengan lebih mudah. Ini file read-only dan tidak dapat diedit.
coolaj86
45

Solusi CoolAJ86 benar dan tidak membahayakan keamanan Anda seperti menonaktifkan semua cek menggunakan rejectUnauthorizedatau NODE_TLS_REJECT_UNAUTHORIZED. Namun, Anda mungkin perlu menyuntikkan sertifikat CA tambahan secara eksplisit.

Saya mencoba dulu root CA yang disertakan oleh modul ssl-root-cas :

require('ssl-root-cas/latest')
  .inject();

Saya masih berakhir dengan UNABLE_TO_VERIFY_LEAF_SIGNATUREkesalahan. Kemudian saya menemukan siapa yang mengeluarkan sertifikat untuk situs web yang saya sambungkan oleh COMODO SSL Analyzer , mengunduh sertifikat dari otoritas itu dan mencoba menambahkan hanya satu itu:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

Saya berakhir dengan kesalahan lain: CERT_UNTRUSTED. Akhirnya, saya menyuntikkan CA root tambahan dan termasuk CA "saya" (tampaknya perantara), yang berfungsi:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');
Ferdinand Prantl
sumber
1
Saya terhubung ke situs web dengan sertifikat yang dikeluarkan oleh COMODO High-Assurance Secure Server CA. Saya mengunduh sertifikat dari halaman unduhan mereka .
Ferdinand Prantl
2
Terima kasih! Untuk masalah saya, saya perlu menambahkan seluruh rantai sertifikat untuk mengatasi kesalahan ini. Untuk referensi orang lain, pos ini menunjukkan kepada saya cara mudah mengekspor file pem yang diperlukan melalui Firefox: superuser.com/a/97203
mfink
Terima kasih atas bantuannya. Dalam kasus saya, pada akhirnya itu adalah konfigurasi yang buruk dari server SSL, bukan node. Tidak semua sertifikat perantara dipasang di server.
Scott Jungwirth
jika Anda mendapatkan sertifikat sebagai .cerjalankan ini openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtuntuk mengonversikannya .crtsebelumnya
0x1gene
8

Untuk Buat React App (di mana kesalahan ini terjadi juga dan pertanyaan ini adalah hasil Google # 1), Anda mungkin menggunakan HTTPS=true npm startdan proxy(dalam package.json) yang pergi ke beberapa HTTPS API yang dengan sendirinya ditandatangani sendiri, saat dalam pengembangan.

Jika itu masalahnya, pertimbangkan untuk berubah proxyseperti ini:

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure memutuskan apakah proxy WebPack memeriksa rantai sertifikat atau tidak dan menonaktifkan yang memastikan sertifikat yang ditandatangani sendiri API tidak diverifikasi sehingga Anda mendapatkan data Anda.

Tomáš Hübelbauer
sumber
4

Mungkin sangat menggoda untuk melakukan rejectUnauthorized: falseatau process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';tidak melakukannya! Itu membuat Anda terkena serangan tengah.

Jawaban lainnya benar karena masalahnya terletak pada kenyataan bahwa sertifikat Anda "ditandatangani oleh perantara CA". Ada solusi mudah untuk ini, yang tidak memerlukan perpustakaan pihak ketiga suka ssl-root-casatau menyuntikkan CA tambahan ke dalam node.

Sebagian besar https klien di opsi dukungan simpul yang memungkinkan Anda menentukan CA per permintaan, yang akan diselesaikan UNABLE_TO_VERIFY_LEAF_SIGNATURE. Berikut adalah contoh sederhana menggunakan httpsmodul built-int node .

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

Namun, jika Anda dapat mengkonfigurasi pengaturan ssl di server hosting Anda, solusi terbaik adalah menambahkan sertifikat perantara ke penyedia hosting Anda. Dengan begitu pemohon klien tidak perlu menentukan CA, karena itu termasuk dalam server itu sendiri. Saya pribadi menggunakan namecheap + heroku. Triknya bagi saya adalah membuat satu file .crt cat yourcertificate.crt bundle.ca-bundle > server.crt. Saya kemudian membuka file ini dan menambahkan baris baru setelah sertifikat pertama. Anda dapat membaca lebih lanjut di

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl

Simon
sumber
Bug ini sebagian besar berasal dari lingkungan lokal, bukan di produksi, Jadi jika Anda berada di lokal tidak masalah untuk melakukan: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
Vivex
@Vivex - tidak apa-apa untuk melakukan itu di lingkungan lokal jika seluruh intinya adalah untuk menguji bagaimana sertifikat SSL Anda bekerja dan bagaimana mereka dapat diteruskan ...
dwanderson
2

Hanya menempatkan ini di sini kalau-kalau itu membantu seseorang, kasus saya berbeda dan sedikit campuran yang aneh. Saya mendapatkan ini berdasarkan permintaan yang diakses melalui superagent - masalahnya tidak ada hubungannya dengan sertifikat (yang diatur dengan benar) dan semua harus dilakukan dengan fakta bahwa saya kemudian melewati hasil superagen melalui waterfall callback air terjun modul async . Untuk memperbaikinya: Alih-alih melewati seluruh hasil, cukup lewati result.bodypanggilan balik air terjun.

k00k
sumber
2

Saya memiliki masalah yang sama. Saya telah mengikuti solusi @ThomasReggi dan @ CoolAJ86 dan bekerja dengan baik tetapi saya tidak puas dengan solusi tersebut.

Karena masalah "UNABLE_TO_VERIFY_LEAF_SIGNATURE" terjadi karena tingkat konfigurasi sertifikasi.

Saya menerima solusi @ thirdender tetapi merupakan solusi parsial. Sesuai dengan situs web resmi nginx , mereka dengan jelas menyebutkan bahwa sertifikat harus merupakan kombinasi dari Sertifikat server dan sertifikat rantai.

masukkan deskripsi gambar di sini

Sharathi RB
sumber
1

Anda juga dapat mencoba dengan menyetel strictSSL ke false, seperti ini:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}
SUBHAJIT GANGULI
sumber
0

Saya memiliki masalah dengan konfigurasi Apache saya setelah menginstal sertifikat GoDaddy pada subdomain. Saya awalnya berpikir itu mungkin masalah dengan Node tidak mengirim Indikator Nama Server (SNI), tapi bukan itu masalahnya. Menganalisis sertifikat SSL subdomain dengan https://www.ssllabs.com/ssltest/ mengembalikan masalah Rantai galat : Tidak lengkap .

Setelah menambahkan gd_bundle-g2-g1.crtfile yang disediakan GoDaddy melalui SSLCertificateChainFilearahan Apache, Node dapat terhubung melalui HTTPS dan kesalahan hilang.

orang ketiga
sumber
0

Anda harus memasukkan sertifikat Menengah di server Anda. Ini memecahkan [Kesalahan: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


sumber
0

Pendekatan lain untuk menyelesaikan masalah ini dengan aman adalah dengan menggunakan modul berikut.

node_extra_ca_certs_mozilla_bundle

Modul ini dapat bekerja tanpa modifikasi kode dengan membuat file PEM yang mencakup semua sertifikat root dan perantara yang dipercaya oleh Mozilla. Anda dapat menggunakan variabel lingkungan berikut (Bekerja dengan Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Untuk menghasilkan file PEM untuk digunakan dengan variabel lingkungan di atas. Anda dapat menginstal modul menggunakan:

npm install --save node_extra_ca_certs_mozilla_bundle

dan kemudian meluncurkan skrip simpul Anda dengan variabel lingkungan.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

Cara lain untuk menggunakan file PEM yang dihasilkan tersedia di:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

CATATAN: Saya adalah penulis modul di atas.

arva
sumber
0

Jika Anda datang ke utas ini karena Anda menggunakan modul node postgres / pg, ada solusi yang lebih baik daripada pengaturan NODE_TLS_REJECT_UNAUTHORIZEDatau rejectUnauthorized, yang akan menyebabkan koneksi tidak aman.

Sebagai gantinya, konfigurasikan opsi "ssl" untuk mencocokkan parameter untuk tls.connect :

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

Saya telah menulis sebuah modul untuk bantuan dengan parsing opsi ini dari variabel lingkungan seperti PGSSLROOTCERT, PGSSLCERT, dan PGSSLKEY:

https://github.com/programmarchy/pg-ssl

Donald
sumber
0

Perintah berikut bekerja untuk saya:

> npm config set strict-ssl false
> npm cache clean --force

Masalahnya adalah Anda mencoba memasang modul dari repositori dengan sertifikat SSL [Secure Sockets Layer] yang buruk atau tidak tepercaya. Setelah Anda membersihkan cache, masalah ini akan teratasi. Anda mungkin perlu mengubahnya menjadi true nanti.

Shagun Pruthi
sumber