2011-11-23 18 views
143

मैं यह पता लगाने कैसे ठीक एक समवर्ती संदर्भHsOpenSSL एपीआई का उचित उपयोग एक टीएलएस सर्वर

जैसे में OpenSSL.Session एपीआई का उपयोग करने के लिए कोशिश कर रहा हूँ लागू करने के लिए मान मैं एक stunnel-style ssl-wrapper लागू करना चाहते हैं, मैं निम्न बुनियादी कंकाल संरचना है, जो एक अनुभवहीन full-duplex tcp-port-forwarder:

runProxy :: PortID -> AddrInfo -> IO() 
runProxy [email protected](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 एपीआई द्वारा प्रदान की गई फ़ंक्शन कॉल के समवर्ती/समांतर निष्पादन (उपरोक्त उपयोग-मामले के संदर्भ में) के लिए डब्ल्यू डब्लूआरटी खतरे कहां हैं?

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

+11

में मुझे लगता है कि यह भी एसओ के लिए एक सवाल व्यापक हो सकता है withOpenSSL के भीतर अपने मुख्य सामान को चलाने के लिए मत भूलना। –

+1

मैं आपको इस पर वापस आऊंगा :-) – Abhineet

+2

दस्तावेज़ का लिंक टूटा हुआ है, यहां वह है जो काम कर रहा है: http://hackage.haskell.org/packages/archive/HsOpenSSL/0.10.2/doc /html/OpenSSL-Session.html –

उत्तर

7

यह आप copySocket, एक एसएसएल के लिए सादे सॉकेट और सादे सॉकेट से एसएसएल से अन्य से डेटा को संभालने के लिए दो अलग-अलग कार्यों के साथ प्रतिस्थापित करने की आवश्यकता करने के लिए: connectToServer संशोधित करने के लिए

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 

फिर आप की जरूरत इतना है कि यह एक SSL कनेक्शन

-- |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 

अंत में, के रूप में

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 
+0

यह पहले से ही बहुत मदद करता है; यह 'stunnels' क्लाइंट-मोड से संबंधित एक स्थानीय-गैर-एसएसएल-टू-रिमोट-एसएसएल प्रॉक्सी प्रदान करता है, क्या आप एक स्थानीय एसएसएल सॉकेट को सुनने के लिए एक उदाहरण भी प्रदान कर सकते हैं (उदाहरण के लिए स्थानीय-एसएसएल-टू-रिमोट -ऑन-एसएसएल प्रॉक्सी)? – hvr

संबंधित मुद्दे