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