টিএলএস সার্ভার বাস্তবায়নের জন্য HsOpenSSL এপিআই এর যথাযথ ব্যবহার


141

আমি সমবর্তী প্রসঙ্গে ওপেনএসএসএল.সেশন এপিআই সঠিকভাবে কীভাবে ব্যবহার করব তা জানার চেষ্টা করছি

যেমন ধরুন আমি একটি বাস্তবায়ন করতে 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 এপিআই দ্বারা প্রদত্ত ফাংশন কলগুলির সমবর্তী / সমান্তরাল সম্পাদনের (উপরের ব্যবহারের ক্ষেত্রে প্রসঙ্গে) বিপদ ডাব্লুআরটি কোথায়?

PS: আমি কীভাবে ব্যতিক্রম এবং সংস্থান-ফাঁসের কোডটিকে শক্তিশালী আর্ট তৈরি করতে পারি তা সম্পূর্ণরূপে বোঝার জন্য লড়াই করছি। সুতরাং, এই প্রশ্নের প্রাথমিক কেন্দ্রীভূত না হলেও, যদি আপনি উপরের কোডটিতে কোনও খারাপ কিছু লক্ষ্য করেন তবে দয়া করে একটি মন্তব্য করুন।


11
আমি মনে করি এটির জন্য এটি খুব বিস্তৃত প্রশ্ন।
ডন স্টুয়ার্ট

1
আমি এটি আপনার কাছে ফিরে আসব :-)
অভিনিত

2
দস্তাবেজ-এ লিঙ্কটি অসম্পূর্ণ, এখানে এক যারা কাজ হল: hackage.haskell.org/packages/archive/HsOpenSSL/0.10.2/doc/html/...
পাসকাল Qyy

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ক্লায়েন্ট-মোডের সাথে সম্পর্কিত একটি স্থানীয়-নন-এসএসএল-থেকে-রিমোট-এসএসএল প্রক্সি সরবরাহ করে, আপনি কীভাবে স্থানীয় এসএসএল সকেট শুনতে হবে (উদাহরণস্বরূপ স্থানীয়-এসএসএল-থেকে-রিমোট-নন- সরবরাহ করতে পারেন) এসএসএল প্রক্সি)?
এইচভিআর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.