J'essaie de comprendre comment utiliser correctement l' API OpenSSL.Session dans un contexte concurrent
Par exemple, supposons que je veuille implémenter un stunnel-style ssl-wrapper
, je m'attendrais à avoir la structure de squelette de base suivante, qui implémente un naïffull-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
Comment puis-je transformer le squelette ci-dessus en un full-duplex ssl-wrapping tcp-forwarding proxy
? Quels sont les dangers WRT pour l'exécution simultanée / parallèle (dans le contexte du cas d'utilisation ci-dessus) des appels de fonction fournis par l'API HsOpenSSL?
PS: J'ai encore du mal à comprendre comment rendre le code robuste face aux exceptions et aux fuites de ressources. Donc, bien que ce ne soit pas l'objet principal de cette question, si vous remarquez quelque chose de mauvais dans le code ci-dessus, veuillez laisser un commentaire.
full-duplex ssl-rewrapping tcp-forwarding
), mais il a utiliséNetwork.TLS
(packagetls
) à la place. Et c'était moche. Vous pouvez le trouver ici , le cas échéant.Réponses:
Pour ce faire, vous devez remplacer
copySocket
par deux fonctions différentes, l'une pour gérer les données du plain socket vers SSL et l'autre de SSL vers le plain socket:Ensuite, vous devez modifier
connectToServer
pour qu'il établisse une connexion SSLet changer
finalize
pour fermer la session SSLEnfin, n'oubliez pas d'exécuter vos éléments principaux à l'intérieur
withOpenSSL
comme dansla source
stunnels
mode client, pourriez-vous également fournir un exemple sur la façon d'écouter un socket local ssl (par exemple pour fournir un local-ssl-to-remote-non- proxy SSL)?