Safe Haskell | None |
---|
This module exports functions that allow you to use TLS-secured TCP connections as streams, as well as utilities to connect to a TLS-enabled TCP server or running your own.
If you need to safely connect to a TLS-enabled TCP server or run your own within a pipes pipeline, then you must use the functions exported from the module Control.Proxy.TCP.TLS.Safe instead.
This module re-exports many functions and types from Network.Simple.TCP.TLS
module in the network-simple
package. You might refer to that module for
more documentation.
- connect :: ClientSettings -> HostName -> ServiceName -> ((Context, SockAddr) -> IO r) -> IO r
- data ClientSettings
- getDefaultClientSettings :: IO ClientSettings
- makeClientSettings :: [Credential] -> Maybe HostName -> CertificateStore -> ClientSettings
- serve :: ServerSettings -> HostPreference -> ServiceName -> ((Context, SockAddr) -> IO ()) -> IO ()
- data ServerSettings
- makeServerSettings :: Credential -> Maybe CertificateStore -> ServerSettings
- listen :: HostPreference -> ServiceName -> ((Socket, SockAddr) -> IO r) -> IO r
- accept :: ServerSettings -> Socket -> ((Context, SockAddr) -> IO b) -> IO b
- acceptFork :: ServerSettings -> Socket -> ((Context, SockAddr) -> IO ()) -> IO ThreadId
- contextReadS :: Proxy p => Context -> () -> Producer p ByteString IO ()
- contextWriteD :: Proxy p => Context -> x -> p x ByteString x ByteString IO r
- contextReadTimeoutS :: Proxy p => Int -> Context -> () -> Producer (EitherP Timeout p) ByteString IO ()
- contextWriteTimeoutD :: Proxy p => Int -> Context -> x -> EitherP Timeout p x ByteString x ByteString IO r
- data HostPreference
- data Credential = Credential !X509 !PrivateKey [X509]
- data Timeout = Timeout String
Client side
Here's how you could run a simple TLS-secured TCP client:
import Control.Proxy.TCP.TLS settings <- getDefaultClientSettings connect settings "www.example.org" "443" $ \(tlsCtx, remoteAddr) -> do putStrLn $ "Secure connection established to " ++ show remoteAddr -- now you may use tlsCtx as you please within this scope, possibly with -- the contextReadS or contextWriteD proxies explained below.
:: ClientSettings | TLS settings. |
-> HostName | Server hostname. |
-> ServiceName | Server service port. |
-> ((Context, SockAddr) -> IO r) | Computation to run after establishing TLS-secured TCP connection to the remote server. Takes the TLS connection context and remote end address. |
-> IO r |
Connect to a TLS-secured TCP server and use the connection
A TLS handshake is performed immediately after establishing the TCP connection.
The connection is properly closed when done or in case of exceptions. If you
need to manage the lifetime of the connection resources yourself, then use
connectTls
instead.
data ClientSettings
Abstract type representing the configuration settings for a TLS client.
Use makeClientSettings
or getDefaultClientSettings
to obtain your
ClientSettings
value.
getDefaultClientSettings :: IO ClientSettings
Get the system default ClientSettings
.
See makeClientSettings
for the for the default TLS settings used.
:: [Credential] | Credentials to provide to the server, if requested. The first one is used in case we can't choose one based on information provided by the server. |
-> Maybe HostName | Explicit Server Name Identification (SNI). |
-> CertificateStore | CAs used to verify the server certificate.
Use |
-> ClientSettings |
Make defaults ClientSettings
.
The following TLS settings are used by default:
- Supported versions
-
TLS10
,TLS11
,TLS12
. - Version reported during ClientHello
-
TLS10
. - Supported cipher suites
- In decreasing order of preference:
cipher_AES256_SHA256
,cipher_AES256_SHA1
,cipher_AES128_SHA256
,cipher_AES128_SHA1
,cipher_RC4_128_SHA1
,cipher_RC4_128_MD5
.
Server side
Here's how you could run a simple TLS-secured TCP server that handles in
different threads each incoming connection to port 4433
at hostname
example.org
. You will need a X509 certificate and a private key appropiate
to be used at that hostname.
import Control.Proxy.TCP.TLS import Network.TLS.Extra (fileReadCertificate, fileReadPrivateKey) cert <- fileReadCertificate "~/example.org.crt" pkey <- fileReadPrivateKey "~/example.org.key" let cred = Credential cert pkey [] settings = makeServerSettings cred Nothing serve settings (Host "example.org") "4433" $ \(tlsCtx, remoteAddr) -> do putStrLn $ "Secure connection established from " ++ show remoteAddr -- now you may use tlsCtx as you please within this scope, possibly with -- the contextReadS or contextWriteD proxies explained below.
If you need more control on the way your server runs, then you can use more
advanced functions such as listen
, accept
and acceptFork
.
:: ServerSettings | TLS settings. |
-> HostPreference | Preferred host to bind. |
-> ServiceName | Service port to bind. |
-> ((Context, SockAddr) -> IO ()) | Computation to run in a different thread once an incomming connection is accepted and a TLS-secured communication is established. Takes the TLS connection context and remote end address. |
-> IO () |
Start a TLS-secured TCP server that accepts incoming connections and handles each of them concurrently, in different threads.
Any acquired network resources are properly closed and discarded when done or in case of exceptions. This function binds a listening socket, accepts an incoming connection, performs a TLS handshake and then safely closes the connection when done or in case of exceptions. You don't need to perform any of those steps manually.
data ServerSettings
Abstract type representing the configuration settings for a TLS server.
Use makeServerSettings
to obtain your ServerSettings
value, and
updateServerParams
to update it.
:: Credential | Server credential. |
-> Maybe CertificateStore | CAs used to verify the client certificate. If specified, then a valid client certificate will be expected during on handshake. |
-> ServerSettings |
Make default ServerSettings
.
The following TLS settings are used by default:
- Supported versions
-
TLS10
,TLS11
,TLS12
. - Supported cipher suites for
TLS10
-
In decreasing order of preference:
cipher_AES256_SHA256
,cipher_AES256_SHA1
,cipher_AES128_SHA256
,cipher_AES128_SHA1
,cipher_RC4_128_SHA1
,cipher_RC4_128_MD5
. The cipher suite preferred by the client is used. - Supported cipher suites for
TLS11
andTLS12
-
In decreasing order of preference:
cipher_AES256_SHA256
,cipher_AES256_SHA1
,cipher_AES128_SHA256
,cipher_AES128_SHA1
. The cipher suite preferred by the client is used.
Listening
:: HostPreference | Preferred host to bind. |
-> ServiceName | Service port to bind. |
-> ((Socket, SockAddr) -> IO r) | Computation taking the listening socket and the address it's bound to. |
-> IO r |
Bind a TCP listening socket and use it.
The listening socket is closed when done or in case of exceptions.
If you prefer to acquire and close the socket yourself, then use
bindSock
and the listen
and sClose
functions from
Network.Socket instead.
Note: maxListenQueue
is tipically 128, which is too small for high
performance servers. So, we use the maximum between maxListenQueue
and
2048 as the default size of the listening queue. The NoDelay
and
ReuseAddr
options are set on the socket.
Accepting
:: ServerSettings | TLS settings. |
-> Socket | Listening and bound socket. |
-> ((Context, SockAddr) -> IO b) | Computation to run in a different thread once an incomming connection is accepted and a TLS-secured communication is established. Takes the TLS connection context and remote end address. |
-> IO b |
Accepts a single incomming TLS-secured TCP connection and use it.
A TLS handshake is performed immediately after establishing the TCP connection.
The connection is properly closed when done or in case of exceptions. If you
need to manage the lifetime of the connection resources yourself, then use
acceptTls
instead.
:: ServerSettings | TLS settings. |
-> Socket | Listening and bound socket. |
-> ((Context, SockAddr) -> IO ()) | Computation to run in a different thread once an incomming connection is accepted and a TLS-secured communication is established. Takes the TLS connection context and remote end address. |
-> IO ThreadId |
Like accept
, except it uses a different thread to performs the TLS
handshake and run the given computation.
TLS context streams
Once you have an established TLS connection Context
, then you can use the
following Proxy
s to interact with the other connection end using streams.
:: Proxy p | |
=> Context | Established TLS connection context. |
-> () | |
-> Producer p ByteString IO () |
Receives decrypted bytes from the remote end, sending them downstream.
Up to 16384
decrypted bytes will be received at once. The TLS connection is
automatically renegotiated if a ClientHello message is received.
If the remote peer closes its side of the connection or EOF is reached, this proxy returns.
:: Proxy p | |
=> Context | Established TLS connection context. |
-> x | |
-> p x ByteString x ByteString IO r |
Encrypts and sends to the remote end the bytes received from upstream, then forwards such same bytes downstream.
If the remote peer closes its side of the connection, this proxy returns.
Requests from downstream are forwarded upstream.
Timeouts
These proxies behave like the similarly named ones above, except they support timing out the interaction with the remote end.
:: Proxy p | |
=> Int | Timeout in microseconds (1/10^6 seconds). |
-> Context | Established TLS connection context. |
-> () | |
-> Producer (EitherP Timeout p) ByteString IO () |
Like contextReadS
, except it throws a Timeout
exception in the
EitherP
proxy transformer if receiving data from the remote end takes
more time than specified.
:: Proxy p | |
=> Int | Timeout in microseconds (1/10^6 seconds). |
-> Context | Established TLS connection context. |
-> x | |
-> EitherP Timeout p x ByteString x ByteString IO r |
Like contextWriteD
, except it throws a Timeout
exception in the
EitherP
proxy transformer if sending data to the remote end takes
more time than specified.
Exports
data HostPreference
Preferred host to bind.
HostAny | Any available host. |
HostIPv4 | Any available IPv4 host. |
HostIPv6 | Any available IPv6 host. |
Host HostName | An explicit host name. |
Eq HostPreference | |
Ord HostPreference | |
Read HostPreference | |
Show HostPreference | |
IsString HostPreference | The following special values are recognized: |
data Credential
Primary certificate, private key and the rest of the certificate chain.
Credential !X509 !PrivateKey [X509] |