pipes-network-tls-0.1.0.0: TLS-secured network connections support for pipes.

Safe HaskellNone

Control.Proxy.TCP.TLS

Contents

Description

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.

Synopsis

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.

connect

Arguments

:: 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.

makeClientSettings

Arguments

:: [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 getSystemCertificateStore to obtain the operating system's defaults.

-> 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.

serve

Arguments

:: 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.

makeServerSettings

Arguments

:: 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 and TLS12
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

listen

Arguments

:: 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

accept

Arguments

:: 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.

acceptFork

Arguments

:: 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 Proxys to interact with the other connection end using streams.

contextReadSSource

Arguments

:: 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.

contextWriteDSource

Arguments

:: 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.

contextReadTimeoutSSource

Arguments

:: 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.

contextWriteTimeoutDSource

Arguments

:: 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.

Constructors

HostAny

Any available host.

HostIPv4

Any available IPv4 host.

HostIPv6

Any available IPv6 host.

Host HostName

An explicit host name.

Instances

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.

Constructors

Credential !X509 !PrivateKey [X509] 

Instances

data Timeout

Exception thrown when a timeout has elapsed.

Constructors

Timeout String

Timeouted with an additional explanatory message.