खराब प्रमाणपत्र के साथ https अनुरोध कैसे करें?


128

कहो कि मैं https://golang.orgप्रोग्राम करवाना चाहता हूं । वर्तमान में golang.org (ssl) के पास एक बुरा प्रमाण पत्र है जो *.appspot.comमुझे इसको चलाने पर So को जारी किया जाता है :

package main

import (
    "log"
    "net/http"
)

func main() {
    _, err := http.Get("https://golang.org/")
    if err != nil {
        log.Fatal(err)
    }
}

मुझे मिलता है (जैसा मुझे उम्मीद थी)

Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org

अब, मैं इस प्रमाण पत्र पर स्वयं भरोसा करना चाहता हूं (स्व-जारी किए गए प्रमाण पत्र की कल्पना करें जहां मैं अंगुली की छाप को सत्यापित कर सकता हूं)): मैं कैसे अनुरोध कर सकता हूं और प्रमाण पत्र को मान्य / भरोसा कर सकता हूं?

मुझे प्रमाणपत्र डाउनलोड करने, इसे अपनी फ़ाइल में लोड करने और tls.Configसंरचना भरने के लिए संभवतः ओपनस्ले का उपयोग करने की आवश्यकता है ?


5
यह एक "खराब प्रमाणपत्र" नहीं है यह एक अलग सीएन के साथ एक प्रमाण पत्र है। InsecureSkipVerify यहां वैध उपयोग नहीं है। आप tls.Config में ServerName सेट करने के लिए जो आप कनेक्ट करने के लिए कोशिश कर रहे हैं से मेल खाना चाहिए। यह StackOverflow पोस्ट गो कोड में इस बड़े सुरक्षा छेद को हर जगह फैलाने का कारण बन रहा है। InsecureSkipVerify सभी पर प्रमाणपत्र की जाँच नहीं करता है। आप जो चाहते हैं वह यह सत्यापित करना है कि प्रमाण पत्र को विश्वसनीय संस्था द्वारा वैध रूप से हस्ताक्षरित किया गया था, भले ही CN होस्टनाम से मेल न खाता हो। सुरंगों और NATS वैध रूप से इसे बेमेल बनाने का कारण बन सकते हैं।
राब

जवाबों:


283

सुरक्षा नोट: सुरक्षा जांच अक्षम करना खतरनाक है और इससे बचा जाना चाहिए

आप डिफ़ॉल्ट ग्राहक के सभी अनुरोधों के लिए विश्व स्तर पर सुरक्षा जांच को अक्षम कर सकते हैं:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    _, err := http.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}

आप ग्राहक के लिए सुरक्षा जांच को अक्षम कर सकते हैं:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    _, err := client.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}

17
मुझे आश्चर्य है कि एक विश्वसनीय प्रमाण पत्र कहां रखा जाए ताकि कनेक्शन का उपयोग किए बिना किया जा सके InsecureSkipVerify: true। क्या यह संभव है?
टॉपस्किप

7
NameToCertificateमदद कर सकते हैं, tls.Configदस्तावेज देखें : golang.org/pkg/crypto/tls/#Config
साइबरबरेलिया

1
यहां कस्टम CA प्रमाणपत्र पूल जोड़ने के लिए एक उदाहरण है: golang.org/pkg/crypto/tls/#example_Dial आप इसे HTTP क्लाइंट में भी उपयोग कर सकते हैं।
बिटबर्ड

7
बहुत से लोग यहाँ समाप्त होते हैं, होस्टनाम चेक को निष्क्रिय करने की कोशिश कर रहे हैं (पूरी तरह से प्रमाणपत्र जाँच अक्षम नहीं करना)। यह गलत उत्तर है। गो को आपको उस होस्ट के CN से मेल करने के लिए tls config में ServerName सेट करने की आवश्यकता है, जिसे आप कनेक्ट कर रहे हैं, यदि यह आपके साथ जुड़ा हुआ dns नाम नहीं है। InsecureSkipVerify पोर्ट पर पुराने-टेलनेट की तुलना में अधिक सुरक्षित नहीं है। इस सेटिंग के साथ कोई प्रमाणीकरण नहीं है। इसके बजाय उपयोगकर्ता सर्वर नाम!
रॉ

8
खबरदार: ऐसा परिवहन जो अपने अधिकांश क्षेत्रों के लिए शून्य-मान का उपयोग करता है और इसलिए सभी चूक खो देता है । जैसा कि नीचे दिए गए उत्तर से पता चलता है, आप उन्हें कॉपी करना चाह सकते हैं। हमें यह पता लगाने में बहुत मज़ा आया कि हम फाइल डिस्क्रिप्टर से बाहर क्यों भाग रहे हैं , क्योंकि हम हार गए Dialer.Timeout
mknecht

26

यहां पर डिफ़ॉल्ट सेटिंग को खोए बिना इसे करने का एक तरीका है DefaultTransport, और उपयोगकर्ता की टिप्पणी के अनुसार नकली अनुरोध की आवश्यकता के बिना।

defaultTransport := http.DefaultTransport.(*http.Transport)

// Create new Transport that ignores self-signed SSL
customTransport := &http.Transport{
  Proxy:                 defaultTransport.Proxy,
  DialContext:           defaultTransport.DialContext,
  MaxIdleConns:          defaultTransport.MaxIdleConns,
  IdleConnTimeout:       defaultTransport.IdleConnTimeout,
  ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
  TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout,
  TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
}

अपडेट करें

छोटा रास्ता:

customTransport := &(*http.DefaultTransport.(*http.Transport)) // make shallow copy
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

उचित तरीका (1.13 गो के अनुसार) ( नीचे उत्तर द्वारा प्रदान किया गया है ):

customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

चेतावनी : केवल परीक्षण / विकास उद्देश्यों के लिए। कुछ भी हो, अपने जोखिम पर आगे बढ़ें !!!


क्या केवल डिफ़ॉल्ट परिवहन सेटिंग्स का उपयोग करके कॉपी करना आसान नहीं होगा mytransportsettings := &(*http.DefaultTransport.(*http.Transport))और फिर केवल टीएलएस क्लाइंट कॉन्फिगर को संशोधित करना होगा mytransportsettings.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}?
TheDiveO

वर्थ एक कोशिश, मुझे लगता है कि मैं यह सुनिश्चित करने की कोशिश कर रहा था कि मैं असली DefaultTransport को संशोधित नहीं कर रहा हूं
जोनाथन लिन

1
यह एक उथली प्रतिलिपि बनाने के लिए सुनिश्चित करता है, जैसे आपने किया, जो चर्चा किए गए उपयोग के मामले के लिए पर्याप्त है। मैं वास्तव में इसे काम कोड में तैनात कर रहा हूं।
दिवियो

19

ये सभी उत्तर गलत हैं! InsecureSkipVerifyएक CN से निपटने के लिए उपयोग न करें जो hostname से मेल नहीं खाता है। गो डेवलपर्स अनजाने में होस्टनाम चेक (जो कि वैध उपयोग - सुरंगों, नटों, साझा क्लस्टर समारोहों, आदि) को अक्षम करने के बारे में अडिग थे, जबकि कुछ ऐसा भी है जो समान दिखता है, लेकिन वास्तव में सर्टिफिकेट चेक को पूरी तरह से नजरअंदाज करता है। आपको यह जानना होगा कि प्रमाणपत्र मान्य है और उस प्रमाणपत्र द्वारा हस्ताक्षरित है जिस पर आपको भरोसा है। लेकिन आम परिदृश्य में, आप जानते हैं कि CN आपके साथ जुड़े होस्टनाम से मेल नहीं खाएगा। उन लोगों के लिए, ServerNameपर सेट करें tls.Config। यदि tls.Config.ServerName== RemoteServerCN, तो प्रमाणपत्र जाँच सफल होगी। ये वो है जो तुम चाहते हो। InsecureSkipVerifyइसका मतलब है कि कोई प्रमाणीकरण नहीं है; और यह एक मैन-इन-द-मिडिल के लिए परिपक्व है; टीएलएस का उपयोग करने के उद्देश्य को पराजित करना।

इसके लिए एक वैध उपयोग है InsecureSkipVerify: इसे होस्ट से कनेक्ट करने और इसके प्रमाणपत्र को हड़पने के लिए उपयोग करें, फिर तुरंत डिस्कनेक्ट करें। यदि आप अपने कोड का उपयोग करने के लिए सेटअप करते हैं InsecureSkipVerify, तो यह आम तौर पर होता है क्योंकि आपने ServerNameठीक से सेट नहीं किया था (यह एक एनवी वर या कुछ और से आने की आवश्यकता होगी - इस आवश्यकता के बारे में पेट-दर्द न करें ... इसे सही तरीके से करें)।

विशेष रूप से, यदि आप क्लाइंट सेर्ट्स का उपयोग करते हैं और प्रमाणीकरण के लिए उन पर भरोसा करते हैं, तो आपके पास मूल रूप से एक नकली लॉगिन है जो वास्तव में किसी भी अधिक लॉगिन नहीं करता है। कोड है कि करता है InsecureSkipVerify, या आप सीखेंगे कि इसके साथ क्या गलत है!


1
क्या आपको ऐसी साइट का पता है जहाँ मैं इसका परीक्षण कर सकता हूँ? golang org अब एक त्रुटि नहीं फेंकता है।
टॉप्सकिप

3
यह उत्तर बहुत भ्रामक है। यदि आप hostname की परवाह किए बिना किसी भी मान्य हस्ताक्षरित प्रमाण पत्र को स्वीकार करते हैं, तो भी आपको वास्तविक सुरक्षा नहीं मिल रही है। मैं आसानी से अपने द्वारा नियंत्रित किसी भी डोमेन के लिए एक वैध प्रमाण पत्र प्राप्त कर सकता हूं; यदि आप टीएलएस चेक के लिए मेरा होस्टनाम निर्दिष्ट करने जा रहे हैं, तो आप यह मान्यता खो देते हैं कि मैं वास्तव में वही हूं जो मैं कहता हूं कि मैं हूं। उस बिंदु पर, यह तथ्य कि प्रमाणपत्र "वैध" है कोई फर्क नहीं पड़ता; यह अभी भी गलत है और आप अभी भी बीच में आदमी की चपेट में हैं।
डैनियल फैरेल

5
एक एंटरप्राइज में जहां आप वास्तव में किसी भी वाणिज्यिक सीए पर भरोसा नहीं करते हैं (यानी: यदि वे उदाहरण के लिए अमेरिका से बाहर हैं), और अपने एंटरप्राइज के लिए एक सीए के साथ बदलें, तो आपको बस यह सत्यापित करने की आवश्यकता है कि यह आपके सीट्स में से एक है। होस्टनाम चेक उन स्थितियों के लिए है जहां उपयोगकर्ता होस्टनाम से मिलान करने की उम्मीद कर रहे हैं, लेकिन DNS सुरक्षित नहीं है। उद्यम में, आप आम तौर पर मशीनों के एक समूह से जुड़ते हैं, जहां होस्टनाम / आईपी के लिए मिलान करना संभव नहीं है, क्योंकि यह नए आईपी के तहत मशीन के सटीक क्लोन हैं। डीएनएस नाम सर्टिफिकेट पाता है, और सर्टिफिकेट आईडी है, डीएनएस नाम नहीं।
रोब

3
विचार यह है कि क्लाइंट कोड केवल एंटरप्राइज़ CA पर भरोसा करता है। यह वास्तव में उपयोग में वर्तमान में सीए प्रणाली की तुलना में कहीं अधिक सुरक्षित है। उस मामले में, कुछ भी नहीं (थावटे, वर्साइन, आदि) ... पर भरोसा किया जाता है। बस सीए जो हम चलाते हैं। वेब ब्राउज़र में विशाल ट्रस्ट सूची होती है। एक-दूसरे से बात करने वाली सेवाओं की ट्रस्ट फ़ाइल में केवल एक CA होता है।
रोब

1
धन्यवाद @Rob मेरे पास एक समान सेटअप है जहां हमारी सेवाएं केवल उसी, एकल सीए पर भरोसा करती हैं और कुछ नहीं। यह महत्वपूर्ण जानकारी और बहुत मदद है।
user99999991

8

यदि आप डिफ़ॉल्ट परिवहन सेटिंग्स को बनाए रखना चाहते हैं तो ऐसा करने का सही तरीका अब है (Go 1.13 के रूप में):

customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client = &http.Client{Transport: customTransport}

Transport.Clone परिवहन की एक गहरी प्रतिलिपि बनाता है। इस तरह आपको किसी भी नए फ़ील्ड को याद करने के बारे में चिंता करने की ज़रूरत नहीं है जो Transportसमय के साथ संरचना में जुड़ जाते हैं ।


7

यदि आप http पैकेज से डिफ़ॉल्ट सेटिंग्स का उपयोग करना चाहते हैं, तो आपको एक नया परिवहन और ग्राहक ऑब्जेक्ट बनाने की आवश्यकता नहीं है, आप इस तरह से प्रमाणपत्र सत्यापन को अनदेखा करने के लिए बदल सकते हैं:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true

7
ऐसा करने के परिणामस्वरूपpanic: runtime error: invalid memory address or nil pointer dereference
ऑस्करराइज

6
यदि आप इससे पहले डिफ़ॉल्ट http अनुरोधकर्ता का उपयोग नहीं करते हैं, तो आपको एक नकली अनुरोध को लागू करना होगा ताकि डिफ़ॉल्ट परिवहन इसे प्रारंभ किया जा सके
कॉर्नेल डेमियन

1
यह होस्टनाम चेक को अक्षम नहीं कर रहा है। यह सभी प्रमाणपत्र जाँच अक्षम करता है। आप जो भी कनेक्ट करते हैं उसके प्रमाणपत्र में CN के बराबर ServerName सेट करने के लिए आपको बाध्य करता है। InsecureSkipVerify एक बदमाश MITM सर्वर से जुड़ेगा जो वास्तविक सेवाओं को आगे बढ़ाने का दिखावा करता है। एक InsecureSkipVerify के लिए केवल वैध उपयोग दूरस्थ अंत के प्रमाणपत्र को हड़पने और तुरंत डिस्कनेक्ट करने के लिए है।
रॉ

यह केवल तभी ठीक है जब आप एक VerifyPeerCertificate निर्दिष्ट करते हैं। यदि आप अभी InsecureSkipVerify सेट करते हैं तो यह बिल्कुल भी जाँच नहीं करता है। लेकिन एक VerifyPeerCert सर्टिफिकेट जोड़ा गया है ताकि आप चेक को फिर से लिख सकें कि आपको क्या चाहिए। आप होस्टनाम को अनदेखा करना चाह सकते हैं, या संभवतः समाप्ति तिथि भी। Google VerifyPeerCertkut के विभिन्न कार्यान्वयनों के लिए जो ऐसा करते हैं।
रॉब

0

आम तौर पर, URL के DNS डोमेन को प्रमाणपत्र के प्रमाणपत्र विषय से मेल खाना चाहिए।

पूर्व समय में यह या तो डोमेन को प्रमाणपत्र के cn के रूप में सेट करके या डोमेन सेट को एक वैकल्पिक विकल्प के रूप में रखकर हो सकता है।

Cn के लिए समर्थन लंबे समय के लिए पदावनत किया गया था (2000 से RFC 2818 में ) और क्रोम ब्राउज़र अब cn को नहीं देखेगा इसलिए आज आपको URL के DNS डोमेन को एक विषय वैकल्पिक नाम के रूप में रखना होगा

RFC 6125 जो cn की जाँच करने से मना करता है यदि SAN DNS डोमेन के लिए मौजूद है, लेकिन अगर IP पते के लिए SAN मौजूद नहीं है। RFC 6125 यह भी दोहराता है कि cn पदावनत है जो पहले से ही RFC 2818 में कहा गया था। और प्रमाणन प्राधिकरण ब्राउज़र फ़ोरम जो वर्तमान में RFC 6125 के साथ संयोजन में मौजूद है, अनिवार्य रूप से इसका मतलब है कि DNS डोमेन नाम के लिए cn को कभी चेक नहीं किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.