hookup-0.2.3: Abstraction over creating network connections with SOCKS5 and TLS

Copyright | (c) Eric Mertens 2016
License | ISC
Maintainer | emertens@gmail.com
Safe Haskell | None
Language | Haskell2010

Hookup

Contents

- Connections
- Reading and writing data
- Configuration
- Errors
- SSL Information

Description

This module provides a uniform interface to network connections with optional support for TLS and SOCKS.

This library is careful to support both IPv4 and IPv6. It will attempt to all of the addresses that a domain name resolves to until one the first successful connection.

Use `connect` and `close` to establish and close network connections.

Use `recv`, `recvLine`, and `send` to receive and transmit data on an open network connection.

TLS and SOCKS parameters can be provided. When both are provided a connection will first be established to the SOCKS server and then the TLS connection will be established through that proxy server. This is most useful when connecting through a dynamic port forward of an SSH client via the `-D` flag.

Synopsis

- data Connection
- connect :: ConnectionParams -> IO Connection
- connectWithSocket :: ConnectionParams -> Socket -> IO Connection
- close :: Connection -> IO ()
- recv :: Connection -> Int -> IO ByteString
- recvLine :: Connection -> Int -> IO (Maybe ByteString)
- send :: Connection -> ByteString -> IO ()
- putBuf :: Connection -> ByteString -> IO ()
- data ConnectionParams = ConnectionParams {
  - cpFamily :: Family
  - cpHost :: HostName
  - cpPort :: PortNumber
  - cpSocks :: Maybe SocksParams
  - cpTls :: Maybe TlsParams
  }
- data SocksParams = SocksParams {
  - spHost :: HostName
  - spPort :: PortNumber
  }
- data TlsParams = TlsParams {
  - tpClientCertificate :: Maybe FilePath
  - tpClientPrivateKey :: Maybe FilePath
  - tpServerCertificate :: Maybe FilePath
  - tpCipherSuite :: String
  - tpInsecure :: Bool
  }
- defaultFamily :: Family
- defaultTlsParams :: TlsParams
- data ConnectionFailure
  - = HostnameResolutionFailure IOError
  - | ConnectionFailure [IOError]
  - | LineTooLong
  - | LineTruncated
  - | SocksError CommandReply
  - | SocksAuthenticationError
  - | SocksProtocolError
  - | SocksBadDomainName
- newtype CommandReply where
  - CommandReply Word8
  - pattern Succeeded :: CommandReply
  - pattern GeneralFailure :: CommandReply
  - pattern NotAllowed :: CommandReply
  - pattern NetUnreachable :: CommandReply
  - pattern HostUnreachable :: CommandReply
  - pattern ConnectionRefused :: CommandReply
  - pattern TTLExpired :: CommandReply
  - pattern CmdNotSupported :: CommandReply
  - pattern AddrNotSupported :: CommandReply
- getPeerCertificate :: Connection -> IO (Maybe X509)
- getPeerCertFingerprintSha1 :: Connection -> IO (Maybe ByteString)
- getPeerCertFingerprintSha256 :: Connection -> IO (Maybe ByteString)
- getPeerCertFingerprintSha512 :: Connection -> IO (Maybe ByteString)
- getPeerPubkeyFingerprintSha1 :: Connection -> IO (Maybe ByteString)
- getPeerPubkeyFingerprintSha256 :: Connection -> IO (Maybe ByteString)
- getPeerPubkeyFingerprintSha512 :: Connection -> IO (Maybe ByteString)

# Connections

data Connection Source #

A connection to a network service along with its read buffer used for line-oriented protocols. The connection could be a plain network connection, SOCKS connected, or TLS.

connect Source #

Arguments

:: ConnectionParams | parameters
-> IO Connection | open connection

Open network connection to TCP service specified by the given parameters.

The resulting connection MUST be closed with `close` to avoid leaking resources.

Throws `IOError`, `SocksError`, `ProtocolError`, `ConnectionFailure`

connectWithSocket Source #

Arguments

:: ConnectionParams | parameters
-> Socket | connected socket
-> IO Connection | open connection

Create a new `Connection` using an already connected socket. This will attempt to start TLS if configured but will ignore any SOCKS server settings as it is assumed that the socket is already actively connected to the intended service.

Throws `ProtocolError`

close Source #

Arguments

:: Connection | open connection
-> IO () |

Close network connection.

# Reading and writing data

recv Source #

Arguments

:: Connection | open connection
-> Int | maximum underlying recv size
-> IO ByteString | next chunk from stream

Receive the next chunk from the stream. This operation will first return the buffer if it contains a non-empty chunk. Otherwise it will request up to the requested number of bytes from the stream.

Throws: `IOError`, `ConnectionAbruptlyTerminated`, `ProtocolError`

recvLine Source #

Arguments

:: Connection | open connection
-> Int | maximum line length
-> IO (Maybe ByteString) | next line or end-of-stream

Receive a line from the network connection. Both `"\r\n"` and `"\n"` are recognized.

Returning `Nothing` means that the peer has closed its half of the connection.

Unterminated lines will raise a `LineTruncated` exception. This can happen if the peer transmits some data and closes its end without transmitting a line terminator.

Throws: `ConnectionAbruptlyTerminated`, `ProtocolError`, `ConnectionFailure`, `IOError`

send Source #

Arguments

:: Connection | open connection
-> ByteString | chunk
-> IO () |

Send bytes on the network connection. This ensures the whole chunk is transmitted, which might take multiple underlying sends.

Throws: `IOError`, `ProtocolError`

putBuf Source #

Arguments

:: Connection | connection
-> ByteString | new head of buffer
-> IO () |

Push a `ByteString` onto the buffer so that it will be the first bytes to be read on the next receive operation. This could perhaps be useful for putting the unused portion of a `recv` back into the buffer for future `recvLine` or `recv` operations.

# Configuration

data ConnectionParams Source #

Parameters for `connect`.

Common defaults for fields: `defaultFamily`, `defaultTlsParams`

The address family can be specified in order to force only IPv4 or IPv6 to be used. The default behavior is to support both. It can be useful to specify exactly one of these in the case that the other is misconfigured and a hostname is resolving to both.

When a `SocksParams` is provided the connection will be established using a SOCKS (version 5) proxy.

When a `TlsParams` is provided the connection negotiate TLS at connect time in order to protect the stream.

Constructors

ConnectionParams |

Fields

- cpFamily :: Family

  IP Protocol family (default `AF_UNSPEC`)

- cpHost :: HostName

  Destination host

- cpPort :: PortNumber

  Destination TCP port

- cpSocks :: Maybe SocksParams

  Optional SOCKS parameters

- cpTls :: Maybe TlsParams

  Optional TLS parameters

data SocksParams Source #

SOCKS connection parameters

Constructors

SocksParams |

Fields

- spHost :: HostName

  SOCKS server host

- spPort :: PortNumber

  SOCKS server port

data TlsParams Source #

TLS connection parameters. These parameters are passed to OpenSSL when making a secure connection.

Constructors

TlsParams |

Fields

- tpClientCertificate :: Maybe FilePath

  Path to client certificate

- tpClientPrivateKey :: Maybe FilePath

  Path to client private key

- tpServerCertificate :: Maybe FilePath

  Path to CA certificate bundle

- tpCipherSuite :: String

  OpenSSL cipher suite name (e.g. `"HIGH"`)

- tpInsecure :: Bool

  Disables certificate checking when `True`

defaultFamily :: Family Source #

Default `Family` value is unspecified and allows both INET and INET6.

defaultTlsParams :: TlsParams Source #

Default values for TLS that use no client certificates, use system CA root, `"HIGH"` cipher suite, and which validate hostnames.

# Errors

data ConnectionFailure Source #

Type for errors that can be thrown by this package.

Constructors

HostnameResolutionFailure IOError | Failure during `getAddrInfo` resolving remote host
ConnectionFailure [IOError] | Failure during `connect` to remote host
LineTooLong | Failure during `recvLine`
LineTruncated | Incomplete line during `recvLine`
SocksError CommandReply | Socks command rejected by server by given reply code
SocksAuthenticationError | Socks authentication method was not accepted
SocksProtocolError | Socks server sent an invalid message or no message.
SocksBadDomainName | Domain name was too long for SOCKS protocol

Instances

Show ConnectionFailure Source # |
Instance details Defined in Hookup Methods showsPrec :: Int -> ConnectionFailure -> ShowS Source # show :: ConnectionFailure -> String Source # showList :: [ConnectionFailure] -> ShowS Source #
Exception ConnectionFailure Source # | `displayException` implemented for prettier messages
Instance details Defined in Hookup Methods toException :: ConnectionFailure -> SomeException Source # fromException :: SomeException -> Maybe ConnectionFailure Source # displayException :: ConnectionFailure -> String Source #

newtype CommandReply Source #

SOCKS command reply codes

Constructors

CommandReply Word8 |

Bundled Patterns

pattern Succeeded :: CommandReply |
pattern GeneralFailure :: CommandReply |
pattern NotAllowed :: CommandReply |
pattern NetUnreachable :: CommandReply |
pattern HostUnreachable :: CommandReply |
pattern ConnectionRefused :: CommandReply |
pattern TTLExpired :: CommandReply |
pattern CmdNotSupported :: CommandReply |
pattern AddrNotSupported :: CommandReply |

Instances

Eq CommandReply Source # |
Instance details Defined in Hookup.Socks5 Methods (==) :: CommandReply -> CommandReply -> Bool Source # (/=) :: CommandReply -> CommandReply -> Bool Source #
Show CommandReply Source # |
Instance details Defined in Hookup.Socks5 Methods showsPrec :: Int -> CommandReply -> ShowS Source # show :: CommandReply -> String Source # showList :: [CommandReply] -> ShowS Source #

# SSL Information

getPeerCertificate :: Connection -> IO (Maybe X509) Source #

Get peer certificate if one exists.

getPeerCertFingerprintSha1 :: Connection -> IO (Maybe ByteString) Source #

getPeerCertFingerprintSha256 :: Connection -> IO (Maybe ByteString) Source #

getPeerCertFingerprintSha512 :: Connection -> IO (Maybe ByteString) Source #

getPeerPubkeyFingerprintSha1 :: Connection -> IO (Maybe ByteString) Source #

getPeerPubkeyFingerprintSha256 :: Connection -> IO (Maybe ByteString) Source #

getPeerPubkeyFingerprintSha512 :: Connection -> IO (Maybe ByteString) Source #