Próbuję dowiedzieć się, jak prawidłowo używać API OpenSSL.Session w kontekście współbieżnym
Załóżmy na przykład, że chcę zaimplementować stunnel-style ssl-wrapper
, spodziewałbym się , że będę miał następującą podstawową strukturę szkieletu, która implementuje naiwność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
Jak przekształcić powyższy szkielet w full-duplex ssl-wrapping tcp-forwarding proxy
? Gdzie są niebezpieczeństwa WRT do równoczesnego / równoległego wykonywania (w kontekście powyższego przypadku użycia) wywołań funkcji udostępnianych przez HsOpenSSL API?
PS: Wciąż staram się w pełni zrozumieć, jak sprawić, by kod był odporny na wyjątki i wycieki zasobów. Tak więc, chociaż nie jest to główny temat tego pytania, jeśli zauważysz coś złego w powyższym kodzie, zostaw komentarz.
full-duplex ssl-rewrapping tcp-forwarding
), ale zamiast tego użyłemNetwork.TLS
(pakiettls
). I to było brzydkie. Możesz go znaleźć tutaj , jeśli w ogóle jesteś zainteresowany.Odpowiedzi:
Aby to zrobić, musisz zastąpić
copySocket
dwie różne funkcje, jedną do obsługi danych ze zwykłego gniazda na SSL, a drugą z SSL do zwykłego gniazda:Następnie musisz zmodyfikować,
connectToServer
aby ustanowił połączenie SSLi zmień,
finalize
aby zamknąć sesję SSLWreszcie, nie zapomnij, aby uruchomić główne rzeczy wewnątrz
withOpenSSL
, jak wźródło
stunnels
trybowi klienta, czy możesz również podać przykład, jak nasłuchiwać lokalnego gniazda ssl (np. aby zapewnić lokalny-zdalny-ssl-nie- ssl proxy)?