Skip to content

Instantly share code, notes, and snippets.

@voltone voltone/learn_you_some_ssl.ex Secret
Last active Apr 9, 2019

Embed
What would you like to do?
Code snippets from 'Learn you some :ssl' talk at ElixirConf EU 2019
iex(1)> :httpc.request('https://elixir-lang.org')
** (exit) exited in: :gen_server.call(:httpc_manager, {:request, # ...
** (EXIT) no process: the process is not alive or there's no process
currently associated with the given name, possibly because its
application isn't started
# ...
iex(2)> :inets.start()
:ok
iex(3)> :ssl.start()
:ok
iex(4)> :httpc.request('https://elixir-lang.org')
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
iex(5)> :httpc.request(:get, {'https://elixir-lang.org', []},
...(5)> [], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
iex(6)> :httpc.request(:get, {'https://selfsigned.voltone.net', []},
...(6)> [], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
iex(7)> :httpc.request(:get, {'https://selfsigned.voltone.net', []},
...(7)> [ssl: [verify: :verify_peer]], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
### Scratching my head for a minute...
iex(8)> :httpc.request(:get, {'https://selfsigned.voltone.net', []},
...(8)> [ssl: [verify: :verify_peer]], [])
{:error,
{:failed_connect,
[
{:to_address, {'selfsigned.voltone.net', 443}},
{:inet, [:inet], {:options, {:cacertfile, []}}}
]}}
iex(9)> h = [{'Connection', 'close'}]
[{'Connection', 'close'}]
iex(10)> :httpc.request(:get, {'https://selfsigned.voltone.net', h},
...(10)> [ssl: [verify: :verify_peer]], [])
{:error,
{:failed_connect,
[
{:to_address, {'selfsigned.voltone.net', 443}},
{:inet, [:inet], {:options, {:cacertfile, []}}}
]}}
iex(11)> :httpc.request(:get, {'https://selfsigned.voltone.net', h},
...(11)> [ssl: [
...(11)> verify: :verify_peer,
...(11)> cacertfile: '/dev/null' # Essentially an empty file
...(11)> ]], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
iex(12)> :httpc.request(:get, {'https://selfsigned.voltone.net', h},
...(12)> [ssl: [
...(12)> verify: :verify_peer,
...(12)> cacertfile: '/dev/null',
...(12)> reuse_sessions: false
...(12)> ]], [])
{:error,
{:failed_connect,
[
{:to_address, {'selfsigned.voltone.net', 443}},
{:inet, [:inet], {:tls_alert, 'bad certificate'}}
]}}
iex(13)> :httpc.request(:get, {'https://selfsigned.voltone.net', h},
...(13)> [ssl: [
...(13)> verify: :verify_peer,
...(13)> cacertfile: '/etc/ssl/certs/ca-certificates.crt',
...(13)> reuse_sessions: false
...(13)> ]], [])
{:error,
{:failed_connect,
[
{:to_address, {'selfsigned.voltone.net', 443}},
{:inet, [:inet], {:tls_alert, 'bad certificate'}}
]}}
iex(14)> :httpc.request(:get, {'https://elixir-lang.org/', h},
...(14)> [ssl: [
...(14)> verify: :verify_peer,
...(14)> cacertfile: '/etc/ssl/certs/ca-certificates.crt',
...(14)> reuse_sessions: false
...(14)> ]], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
iex(15)> :httpc.request(:get, {'https://sha256.badssl.com/', h},
...(15)> [ssl: [
...(15)> verify: :verify_peer,
...(15)> cacertfile: '/etc/ssl/certs/ca-certificates.crt',
...(15)> reuse_sessions: false
...(15)> ]], [])
{:error,
{:failed_connect,
[
{:to_address, {'sha256.badssl.com', 443}},
{:inet, [:inet], {:tls_alert, 'handshake failure'}}
]}}
# Log message: TLS client: In state certify at ssl_handshake.erl:1380
# generated CLIENT ALERT: Fatal - Handshake Failure -
# {bad_cert,hostname_check_failed}
iex(16)> :httpc.request(:get, {'https://sha256.badssl.com/', h},
...(16)> [ssl: [
...(16)> verify: :verify_peer,
...(16)> cacertfile: '/etc/ssl/certs/ca-certificates.crt',
...(16)> customize_hostname_check: [
...(16)> match_fun:
...(16)> :public_key.pkix_verify_hostname_match_fun(:https)
...(16)> ],
...(16)> reuse_sessions: false
...(16)> ]], [])
{:ok,
{{'HTTP/1.1', 200, 'OK'},
# ...
# Assuming HTTPoison in deps and started, e.g. from `iex -S mix`
iex(17)> HTTPoison.get("https://elixir-lang.org")
{:ok,
%HTTPoison.Response{
# ...
iex(19)> HTTPoison.get("https://selfsigned.voltone.net", [],
...(19)> ssl: [
...(19)> versions: [:"tlsv1.2"]
...(19)> ])
{:ok,
%HTTPoison.Response{
# ...
iex(20)> :httpc.request(:get, {'https://revoked.badssl.com/', h},
...(20)> [ssl: [
...(20)> verify: :verify_peer,
...(20)> cacertfile: '/etc/ssl/certs/ca-certificates.crt',
...(20)> customize_hostname_check: [
...(20)> match_fun:
...(20)> :public_key.pkix_verify_hostname_match_fun(:https)
...(20)> ],
...(20)> crl_check: true,
...(20)> crl_cache: {:ssl_crl_cache, {:internal, [http: 30000]}},
...(20)> reuse_sessions: false
...(20)> ]], [])
{:error,
{:failed_connect,
[
{:to_address, {'revoked.badssl.com', 443}},
{:inet, [:inet], {:tls_alert, 'certificate revoked'}}
]}}
iex(21)> :ssl.cipher_suites(:default, :"tlsv1.2") |>
...(21)> :ssl.filter_cipher_suites(
...(21)> key_exchange: &(&1 == :ecdhe_rsa),
...(21)> mac: &(&1 == :aead)
...(21)> )
[
%{cipher: :aes_256_gcm, key_exchange: :ecdhe_rsa, mac: :aead,
prf: :sha384},
%{cipher: :aes_128_gcm, key_exchange: :ecdhe_rsa, mac: :aead,
prf: :sha256}
]
# Alternatively...
# :ssl.cipher_suites(:default, :”tlsv1.2") |>
# Enum.filter(&match?(%{key_exchange: :ecdhe_rsa, mac: :aead}, &1))
iex(22)> ciphers = :ssl.cipher_suites(:default, :"tlsv1.2") |>
...(22)> :ssl.filter_cipher_suites(
...(22)> cipher: &(&1 == :chacha20_poly1305)
...(22)> )
[]
iex(23)> :ssl.listen(8443, ciphers: ciphers)
{:ok,
{:sslsocket, nil,
# ...snip...
[
<<192, 44>>, # ECDHE-ECDSA-AES256-GCM-SHA384
<<192, 48>>, # ECDHE-RSA-AES256-GCM-SHA384
<<192, 36>>, # ECDHE-ECDSA-AES256-SHA384
<<192, 40>>, # ECDHE-RSA-AES256-SHA384
# ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.