Documentation ¶
Index ¶
- Constants
- func DeriveTLSPassthroughKey(obfuscatedKey string) ([]byte, error)
- func MakeTLSPassthroughMessage(obfuscatedKey string) ([]byte, error)
- func VerifyTLSPassthroughMessage(passthroughKey, message []byte) bool
- type ObfuscatedSSHConn
- func NewClientObfuscatedSSHConn(conn net.Conn, obfuscationKeyword string, ...) (*ObfuscatedSSHConn, error)
- func NewObfuscatedSSHConn(mode ObfuscatedSSHConnMode, conn net.Conn, obfuscationKeyword string, ...) (*ObfuscatedSSHConn, error)
- func NewServerObfuscatedSSHConn(conn net.Conn, obfuscationKeyword string, seedHistory *SeedHistory, ...) (*ObfuscatedSSHConn, error)
- type ObfuscatedSSHConnMode
- type ObfuscatedSSHReadState
- type ObfuscatedSSHWriteState
- type Obfuscator
- func (obfuscator *Obfuscator) GetDerivedPRNG(salt string) (*prng.PRNG, error)
- func (obfuscator *Obfuscator) GetPaddingLength() int
- func (obfuscator *Obfuscator) ObfuscateClientToServer(buffer []byte)
- func (obfuscator *Obfuscator) ObfuscateServerToClient(buffer []byte)
- func (obfuscator *Obfuscator) SendSeedMessage() []byte
- type ObfuscatorConfig
- type SeedHistory
- type SeedHistoryConfig
Constants ¶
const ( HISTORY_SEED_TTL = 24 * time.Hour HISTORY_SEED_MAX_ENTRIES = 1000000 HISTORY_CLIENT_IP_TTL = 2 * time.Minute HISTORY_CLIENT_IP_MAX_ENTRIES = 10000 )
const ( SSH_MAX_SERVER_LINE_LENGTH = 1024 SSH_PACKET_PREFIX_LENGTH = 5 // uint32 + byte SSH_MAX_PACKET_LENGTH = 256 * 1024 // OpenSSH max packet length SSH_MSG_NEWKEYS = 21 SSH_MAX_PADDING_LENGTH = 255 // RFC 4253 sec. 6 SSH_PADDING_MULTIPLE = 16 // Default cipher block size )
const ( OBFUSCATION_CONN_MODE_CLIENT = iota OBFUSCATION_CONN_MODE_SERVER )
const ( OBFUSCATION_READ_STATE_IDENTIFICATION_LINES = iota OBFUSCATION_READ_STATE_KEX_PACKETS OBFUSCATION_READ_STATE_FLUSH OBFUSCATION_READ_STATE_FINISHED )
const ( OBFUSCATION_WRITE_STATE_CLIENT_SEND_SEED_MESSAGE = iota OBFUSCATION_WRITE_STATE_SERVER_SEND_IDENTIFICATION_LINE_PADDING OBFUSCATION_WRITE_STATE_IDENTIFICATION_LINE OBFUSCATION_WRITE_STATE_KEX_PACKETS OBFUSCATION_WRITE_STATE_FINISHED )
const ( OBFUSCATE_SEED_LENGTH = 16 OBFUSCATE_KEY_LENGTH = 16 OBFUSCATE_HASH_ITERATIONS = 6000 OBFUSCATE_MAX_PADDING = 8192 OBFUSCATE_MAGIC_VALUE = 0x0BF5CA7E OBFUSCATE_CLIENT_TO_SERVER_IV = "client_to_server" OBFUSCATE_SERVER_TO_CLIENT_IV = "server_to_client" )
const ( TLS_PASSTHROUGH_NONCE_SIZE = 16 TLS_PASSTHROUGH_KEY_SIZE = 32 TLS_PASSTHROUGH_MESSAGE_SIZE = 32 )
Variables ¶
This section is empty.
Functions ¶
func DeriveTLSPassthroughKey ¶
DeriveTLSPassthroughKey derives a TLS passthrough key from a master obfuscated key. The resulting key can be cached and passed to VerifyTLSPassthroughMessage.
func MakeTLSPassthroughMessage ¶
MakeTLSPassthroughMessage generates a unique TLS passthrough message using the passthrough key derived from a master obfuscated key.
The passthrough message demonstrates knowledge of the obfuscated key.
func VerifyTLSPassthroughMessage ¶
VerifyTLSPassthroughMessage checks that the specified passthrough message was generated using the passthrough key.
Types ¶
type ObfuscatedSSHConn ¶ added in v1.0.9
ObfuscatedSSHConn wraps a Conn and applies the obfuscated SSH protocol to the traffic on the connection: https://github.com/brl/obfuscated-openssh/blob/master/README.obfuscation
ObfuscatedSSHConn is used to add obfuscation to golang's stock "ssh" client and server without modification to that standard library code. The underlying connection must be used for SSH traffic. This code injects the obfuscated seed message, applies obfuscated stream cipher transformations, and performs minimal parsing of the SSH protocol to determine when to stop obfuscation (after the first SSH_MSG_NEWKEYS is sent and received).
WARNING: doesn't fully conform to net.Conn concurrency semantics: there's no synchronization of access to the read/writeBuffers, so concurrent calls to one of Read or Write will result in undefined behavior.
func NewClientObfuscatedSSHConn ¶
func NewClientObfuscatedSSHConn( conn net.Conn, obfuscationKeyword string, obfuscationPaddingPRNGSeed *prng.Seed, minPadding, maxPadding *int) (*ObfuscatedSSHConn, error)
NewClientObfuscatedSSHConn creates a client ObfuscatedSSHConn. See documentation in NewObfuscatedSSHConn.
func NewObfuscatedSSHConn ¶ added in v1.0.9
func NewObfuscatedSSHConn( mode ObfuscatedSSHConnMode, conn net.Conn, obfuscationKeyword string, obfuscationPaddingPRNGSeed *prng.Seed, minPadding, maxPadding *int, seedHistory *SeedHistory, irregularLogger func( clientIP string, err error, logFields common.LogFields)) (*ObfuscatedSSHConn, error)
NewObfuscatedSSHConn creates a new ObfuscatedSSHConn. The underlying conn must be used for SSH traffic and must have transferred no traffic.
In client mode, NewObfuscatedSSHConn does not block or initiate network I/O. The obfuscation seed message is sent when Write() is first called.
In server mode, NewObfuscatedSSHConn cannot completely initialize itself without the seed message from the client to derive obfuscation keys. So NewObfuscatedSSHConn blocks on reading the client seed message from the underlying conn.
obfuscationPaddingPRNGSeed is required and used only in OBFUSCATION_CONN_MODE_CLIENT mode and allows for optional replay of the same padding: both in the initial obfuscator message and in the SSH KEX sequence. In OBFUSCATION_CONN_MODE_SERVER mode, the server obtains its PRNG seed from the client's initial obfuscator message, resulting in the server replaying its padding as well.
seedHistory and irregularLogger are optional ObfuscatorConfig parameters used only in OBFUSCATION_CONN_MODE_SERVER.
func NewServerObfuscatedSSHConn ¶
func NewServerObfuscatedSSHConn( conn net.Conn, obfuscationKeyword string, seedHistory *SeedHistory, irregularLogger func( clientIP string, err error, logFields common.LogFields)) (*ObfuscatedSSHConn, error)
NewServerObfuscatedSSHConn creates a server ObfuscatedSSHConn. See documentation in NewObfuscatedSSHConn.
func (*ObfuscatedSSHConn) GetDerivedPRNG ¶ added in v1.0.10
func (conn *ObfuscatedSSHConn) GetDerivedPRNG(salt string) (*prng.PRNG, error)
GetDerivedPRNG creates a new PRNG with a seed derived from the ObfuscatedSSHConn padding seed and distinguished by the salt, which should be a unique identifier for each usage context.
In OBFUSCATION_CONN_MODE_SERVER mode, the ObfuscatedSSHConn padding seed is obtained from the client, so derived PRNGs may be used to replay sequences post-initial obfuscator message.
func (*ObfuscatedSSHConn) GetMetrics ¶ added in v1.0.9
func (conn *ObfuscatedSSHConn) GetMetrics() common.LogFields
GetMetrics implements the common.MetricsSource interface.
type ObfuscatedSSHConnMode ¶ added in v1.0.9
type ObfuscatedSSHConnMode int
type ObfuscatedSSHReadState ¶ added in v1.0.9
type ObfuscatedSSHReadState int
type ObfuscatedSSHWriteState ¶ added in v1.0.9
type ObfuscatedSSHWriteState int
type Obfuscator ¶
type Obfuscator struct {
// contains filtered or unexported fields
}
Obfuscator implements the seed message, key derivation, and stream ciphers for: https://github.com/brl/obfuscated-openssh/blob/master/README.obfuscation
Limitation: the RC4 cipher is vulnerable to ciphertext malleability and the "magic" value provides only weak authentication due to its small size. Increasing the size of the magic field will break compatibility with legacy clients. New protocols and schemes should not use this obfuscator.
func NewClientObfuscator ¶
func NewClientObfuscator( config *ObfuscatorConfig) (obfuscator *Obfuscator, err error)
NewClientObfuscator creates a new Obfuscator, staging a seed message to be sent to the server (by the caller) and initializing stream ciphers to obfuscate data.
ObfuscatorConfig.PaddingPRNGSeed allows for optional replay of the obfuscator padding and must not be nil.
func NewServerObfuscator ¶
func NewServerObfuscator( config *ObfuscatorConfig, clientIP string, clientReader io.Reader) (obfuscator *Obfuscator, err error)
NewServerObfuscator creates a new Obfuscator, reading a seed message directly from the clientReader and initializing stream ciphers to obfuscate data.
ObfuscatorConfig.PaddingPRNGSeed is not used, as the server obtains a PRNG seed from the client's initial obfuscator message; this scheme allows for optional replay of the downstream obfuscator padding.
The clientIP value is used by the SeedHistory, which retains client IP values for a short time. See SeedHistory documentation.
func (*Obfuscator) GetDerivedPRNG ¶ added in v1.0.10
func (obfuscator *Obfuscator) GetDerivedPRNG(salt string) (*prng.PRNG, error)
GetDerivedPRNG creates a new PRNG with a seed derived from the obfuscator padding seed and distinguished by the salt, which should be a unique identifier for each usage context.
For NewServerObfuscator, the obfuscator padding seed is obtained from the client, so derived PRNGs may be used to replay sequences post-initial obfuscator message.
func (*Obfuscator) GetPaddingLength ¶ added in v1.0.9
func (obfuscator *Obfuscator) GetPaddingLength() int
GetPaddingLength returns the client seed message padding length. Only valid for NewClientObfuscator.
func (*Obfuscator) ObfuscateClientToServer ¶
func (obfuscator *Obfuscator) ObfuscateClientToServer(buffer []byte)
ObfuscateClientToServer applies the client RC4 stream to the bytes in buffer.
func (*Obfuscator) ObfuscateServerToClient ¶
func (obfuscator *Obfuscator) ObfuscateServerToClient(buffer []byte)
ObfuscateServerToClient applies the server RC4 stream to the bytes in buffer.
func (*Obfuscator) SendSeedMessage ¶
func (obfuscator *Obfuscator) SendSeedMessage() []byte
SendSeedMessage returns the seed message created in NewObfuscatorClient, removing the reference so that it may be garbage collected.
type ObfuscatorConfig ¶
type ObfuscatorConfig struct { Keyword string PaddingPRNGSeed *prng.Seed MinPadding *int MaxPadding *int SeedHistory *SeedHistory StrictHistoryMode bool IrregularLogger func(clientIP string, err error, logFields common.LogFields) }
ObfuscatorConfig specifies an Obfuscator configuration.
type SeedHistory ¶
type SeedHistory struct {
// contains filtered or unexported fields
}
SeedHistory maintains a history of recently observed obfuscation seed values. This history is used to identify duplicate seed messages.
As a heurististic to exclude expected duplicates, due to, for example, meek retries, the source client IP is retained for comparison for a short duration -- long enough to cover meek retries without retaining client IPs in memory long past a client connection lifetime.
func NewSeedHistory ¶
func NewSeedHistory(config *SeedHistoryConfig) *SeedHistory
NewSeedHistory creates a new SeedHistory. Config is optional.
func (*SeedHistory) AddNew ¶
func (h *SeedHistory) AddNew( strictMode bool, clientIP string, seedType string, seed []byte) (bool, *common.LogFields)
AddNew adds a new seed value to the history. If the seed value is already in the history, and an expected case such as a meek retry is ruled out (or strictMode is on), AddNew returns false.
When a duplicate seed is found, a common.LogFields instance is returned, populated with event data. Log fields may be returned in either the false or true case.