TLS सर्वर को लागू करने के लिए HsOpenSSL API का उचित उपयोग


141

मैं एक समसामयिक संदर्भ में OpenSSL.Session एपीआई का सही तरीके से उपयोग करने का तरीका जानने की कोशिश कर रहा हूं

उदाहरण के लिए stunnel-style ssl-wrapper, मुझे लगता है कि मैं इसे लागू करना चाहता हूं , मुझे निम्नलिखित बुनियादी कंकाल संरचना की उम्मीद है, जो एक भोले को लागू करता हैfull-duplex tcp-port-forwarder:

runProxy :: PortID -> AddrInfo -> IO ()
runProxy localPort@(PortNumber lpn) serverAddrInfo = do
  listener <- listenOn localPort

  forever $ do
    (sClient, clientAddr) <- accept listener

    let finalize sServer = do
            sClose sServer
            sClose sClient

    forkIO $ do
        tidToServer <- myThreadId
        bracket (connectToServer serverAddrInfo) finalize $ \sServer -> do
            -- execute one 'copySocket' thread for each data direction
            -- and make sure that if one direction dies, the other gets
            -- pulled down as well
            bracket (forkIO (copySocket sServer sClient
                             `finally` killThread tidToServer))
                    (killThread) $ \_ -> do
                copySocket sClient sServer -- "controlling" thread

 where
  -- |Copy data from source to dest until EOF occurs on source
  -- Copying may also be aborted due to exceptions
  copySocket :: Socket -> Socket -> IO ()
  copySocket src dst = go
   where
    go = do
        buf <- B.recv src 4096
        unless (B.null buf) $ do
            B.sendAll dst buf
            go

  -- |Create connection to given AddrInfo target and return socket
  connectToServer saddr = do
    sServer <- socket (addrFamily saddr) Stream defaultProtocol
    connect sServer (addrAddress saddr)
    return sServer

मैं उपरोक्त कंकाल को एक में कैसे बदलूं full-duplex ssl-wrapping tcp-forwarding proxy? HsOpenSSL एपीआई द्वारा प्रदान किए गए फ़ंक्शन कॉल के समवर्ती / समानांतर निष्पादन (उपरोक्त उपयोग के मामले के संदर्भ में) WRT के खतरे कहाँ हैं?

पुनश्च: मैं अभी भी पूरी तरह से समझने के लिए संघर्ष कर रहा हूं कि अपवाद और संसाधन-लीक को कोड को मजबूत कैसे बनाया जाए। इसलिए, इस प्रश्न का प्राथमिक ध्यान नहीं होने के बावजूद, यदि आपको ऊपर दिए गए कोड में कुछ बुरा दिखाई देता है, तो कृपया एक टिप्पणी छोड़ दें।


11
मुझे लगता है कि यह एसओ के लिए बहुत व्यापक प्रश्न हो सकता है।
डॉन स्टीवर्ट

1
मैं आपको इस पर वापस आता हूँ :-)
अभिनीत

2
डॉक्टर के लिए लिंक टूट गया है, यहाँ एक है जो काम कर रहा है: hackage.haskell.org/packages/archive/HsOpenSSL/0.10.2/doc/html/…
पास्कल कय्य

4
मैंने कुछ ऐसा ही बनाया ( full-duplex ssl-rewrapping tcp-forwarding), लेकिन इसका इस्तेमाल Network.TLS(पैकेज tls) के बजाय किया। और यह बदसूरत था। आप इसे यहां पा सकते हैं , अगर सभी रुचि रखते हैं।

जवाबों:


7

ऐसा करने के लिए आपको copySocketदो अलग-अलग कार्यों को बदलने की जरूरत है , एक सादे सॉकेट से एसएसएल तक डेटा को संभालने के लिए और दूसरा एसएसएल से सादे सॉकेट के लिए।

  copyIn :: SSL.SSL -> Socket -> IO ()
  copyIn src dst = go
   where
    go = do
        buf <- SSL.read src 4096
        unless (B.null buf) $ do
            SB.sendAll dst buf
            go

  copyOut :: Socket -> SSL.SSL -> IO ()
  copyOut src dst = go
   where
    go = do
        buf <- SB.recv src 4096
        unless (B.null buf) $ do
            SSL.write dst buf
            go

फिर आपको संशोधित करने की आवश्यकता है connectToServerताकि यह एक एसएसएल कनेक्शन स्थापित करे

  -- |Create connection to given AddrInfo target and return socket
  connectToServer saddr = do
    sServer <- socket (addrFamily saddr) Stream defaultProtocol
    putStrLn "connecting"
    connect sServer (addrAddress saddr)
    putStrLn "establishing ssl context"
    ctx <- SSL.context
    putStrLn "setting ciphers"
    SSL.contextSetCiphers ctx "DEFAULT"
    putStrLn "setting verfication mode"
    SSL.contextSetVerificationMode ctx SSL.VerifyNone
    putStrLn "making ssl connection"
    sslServer <- SSL.connection ctx sServer
    putStrLn "doing handshake"
    SSL.connect sslServer
    putStrLn "connected"
    return sslServer

और finalizeएसएसएल सत्र को बंद करने के लिए बदलें

let finalize sServer = do
        putStrLn "shutting down ssl"
        SSL.shutdown sServer SSL.Unidirectional
        putStrLn "closing server socket"
        maybe (return ()) sClose (SSL.sslSocket sServer)
        putStrLn "closing client socket"
        sClose sClient

अंत में, के withOpenSSLरूप में भीतर अपने मुख्य सामान को चलाने के लिए मत भूलना

main = withOpenSSL $ do
    let hints = defaultHints { addrSocketType = Stream, addrFamily = AF_INET }
    addrs <- getAddrInfo (Just hints) (Just "localhost") (Just "22222")
    let addr = head addrs
    print addr
    runProxy (PortNumber 11111) addr

यह पहले से ही बहुत मदद करता है; यह stunnelsक्लाइंट-मोड के अनुरूप एक स्थानीय-गैर-एसएसएल-से-रिमोट-एसएलएस प्रॉक्सी प्रदान करता है, क्या आप एक उदाहरण भी प्रदान कर सकते हैं कि कैसे स्थानीय एसएलएस सॉकेट को सुनना है (उदाहरण के लिए एक स्थानीय-एसएसएल-टू-रिमोट-गैर- एसएसएल प्रॉक्सी)?
hvr
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.