Estoy tratando de descubrir cómo usar correctamente la API OpenSSL.Session en un contexto concurrente
Por ejemplo, suponga que quiero implementar un stunnel-style ssl-wrapper
, esperaría tener la siguiente estructura básica de esqueleto, que implementa un ingenuofull-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
¿Cómo transformo el esqueleto anterior en un full-duplex ssl-wrapping tcp-forwarding proxy
? ¿Dónde están los peligros WRT para la ejecución concurrente / paralela (en el contexto del caso de uso anterior) de las llamadas a funciones proporcionadas por la API HsOpenSSL?
PD: Todavía estoy luchando por comprender por completo cómo hacer que el código sea robusto para excepciones y fugas de recursos. Entonces, aunque no sea el foco principal de esta pregunta, si nota algo malo en el código anterior, deje un comentario.
full-duplex ssl-rewrapping tcp-forwarding
), pero en su lugar usóNetwork.TLS
(paquetetls
). Y fue feo. Puede encontrarlo aquí , si está interesado.Respuestas:
Para hacer esto, debe reemplazarlo
copySocket
con dos funciones diferentes, una para manejar los datos del socket simple a SSL y la otra de SSL al socket simple:Luego debe modificar
connectToServer
para que establezca una conexión SSLy cambiar
finalize
para cerrar la sesión SSLFinalmente, no olvides ejecutar tus cosas principales dentro
withOpenSSL
como enfuente
stunnels
modo cliente, ¿podría también proporcionar un ejemplo de cómo escuchar un socket ssl local (por ejemplo, para proporcionar un local-ssl-to-remote-non- proxy SSL)?