Estou tentando descobrir como usar corretamente o API OpenSSL.Session em um contexto simultâneo
Por exemplo, suponha que eu queira implementar um stunnel-style ssl-wrapper
, eu esperaria ter a seguinte estrutura básica do esqueleto, que implementa uma ingênuafull-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
Como faço para transformar o esqueleto acima em um full-duplex ssl-wrapping tcp-forwarding proxy
? Onde estão os perigos do WRT para a execução simultânea / paralela (no contexto do caso de uso acima) das chamadas de função fornecidas pela API HsOpenSSL?
PS: Ainda estou lutando para compreender completamente como tornar o código robusto, com exceções e vazamentos de recursos. Portanto, apesar de não ser o foco principal desta pergunta, se você notar algo ruim no código acima, deixe um comentário.
full-duplex ssl-rewrapping tcp-forwarding
), mas ele usouNetwork.TLS
(pacotetls
). E foi feio. Você pode encontrá-lo aqui , se estiver interessado.Respostas:
Para fazer isso, é necessário substituir
copySocket
por duas funções diferentes, uma para manipular dados do soquete simples para SSL e a outra do SSL para o soquete simples:Então você precisa modificar
connectToServer
para que ele estabeleça uma conexão SSLe mude
finalize
para desligar a sessão SSLPor fim, não se esqueça de executar suas principais coisas
withOpenSSL
como dentrofonte
stunnels
modo cliente; você também pode fornecer um exemplo de como ouvir um soquete ssl local (por exemplo, para fornecer um local-ssl-para-remoto-não- proxy SSL)?