Skip to content

net.mbedtls: Server Name Indication (SNI) - #22012

Merged
spytheman merged 13 commits into
vlang:masterfrom
martinskou:master
Aug 11, 2024
Merged

spytheman merged 13 commits into
vlang:masterfrom
martinskou:master

Conversation

@martinskou

Copy link
Copy Markdown
Contributor

net.mbedtls: Makes it possible to use Server Name Indication (SNI). The mbedtls.SSLConnectConfig is extended with a callback get_certificate which on connection receives a hostname and can return the certificate which the connection should use.

Server Name Indication (SNI) is an extension which is designes to enable usage of multiple domains be the same server on the same port. This extension is used be fx Nginx and Caddy.

Server Name Indication (SNI) is defined in RFC 6066. See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/use-sni/

Example:

import io
import os
import net.mbedtls

fn get_cert(host string) !mbedtls.SNICerts {
	// callback to return the certificates to use for the connection, based on the host
	sni_certs := mbedtls.SNICerts{
		cert: os.read_file('cert/${host}.crt') or { return error('Failed to read certificate') }
		key: os.read_file('cert/${host}.key') or { return error('Failed to read key') }
	}
	return sni_certs
}

fn main() {
	mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{
		verify: os.resource_abs_path('cert/ca.crt')
		cert: os.resource_abs_path('cert/defaultserver.crt')
		cert_key: os.resource_abs_path('cert/defaultserver.key')
		validate: false
		get_certificate: get_cert // set the callback to enable SNI
	})!

	mut client := server.accept()!	
}

Imported functions needed to use SNI
Allow for a get_certificate callback in SSLConnectConfig. If set, the callback will use SNI to make the callback select the certificate to use for the connection.
SSL Server example using the SNI extension
Updated function description
@martinskou martinskou changed the title Mbedtls Server Name Indication (SNI) net.mbedtls: Server Name Indication (SNI) Aug 9, 2024
@spytheman

Copy link
Copy Markdown
Contributor

The example examples/ssl_server/server_sni.v, just hangs for me.
Should not the client try to at least send the server a host header?

@martinskou

Copy link
Copy Markdown
Contributor Author

The example examples/ssl_server/server_sni.v, just hangs for me. Should not the client try to at least send the server a host header?

Yes it should. But be aware that the browser does not send any host name if a domain is not used. So 127.0.0.1 will not work.

It can be tested using fx:

curl -vik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/

or

openssl s_client -connect 0.0.0.0:8443 -servername 1x.dk -debug

Comment thread vlib/net/mbedtls/ssl_connection.c.v Outdated
@martinskou

Copy link
Copy Markdown
Contributor Author

I have updated the code.
See examples/ssl_server/server_sni_advanced.v for an example using multiple certificates.
The original (default) certificates in the mbedtls.SSLListener is no longer changed (the get_certificate callback must supply a new mbedtls.SSLCerts and this eliminates the issue about thread safety.

* master:
  flag: add optional value description to string parameters (#22024)
  fmt: fix alignment of struct init fields (#22025)
  cgen: fix selector with interface var (#22006)
  checker: add a deprecation warning for `const ()` groups (an error after 2025-01-01) (#22019)
  v2: fix a notice for `v cmd/v2/v2.v`
  tools: reduce number of os/fs calls done by `v where`; ignore tests/ folders
  tools: make `v where` ignore .git/ folders (they contain binary files); let `-dir .` work recursively, so that `-dir vlib` works
  fmt: cleanup fields alignment (#22018)
  veb: change example description, to avoid repetitive wording (ease debugging of issue#22017)
  all: allow multi return as fn argument (#21991)
  examples: change // to blank line in 2048.v too, after 793b66d
  all: change single blank comment to blank line (#22016)
  scanner: guard against scanner panic, discovered by fuzzing in PR#22016
  time: `d`,`c`,`dd`,`ddd`,`dddd` pattern support for parse_format() (#22003)
  ast, parser, fmt: cleanup fmt of struct fields with empty line (#22014)
  ast, parser, fmt: fix fmt of enum fields with empty line (#22015)
@spytheman

Copy link
Copy Markdown
Contributor

These new public APIs will need doc comments too, so that the CI can pass:

vlib/net/mbedtls/ssl_connection.c.v:94:0:pub fn (mut c SSLCerts) cleanup() 
vlib/net/mbedtls/ssl_connection.c.v:34:0:pub fn new_sslcerts() &SSLCerts 
vlib/net/mbedtls/ssl_connection.c.v:68:0:pub fn new_sslcerts_from_file(verify string, cert string, cert_key string) !&SSLCerts 
vlib/net/mbedtls/ssl_connection.c.v:42:0:pub fn new_sslcerts_in_memory(verify string, cert string, cert_key string) !&SSLCerts 

@spytheman

Copy link
Copy Markdown
Contributor

I've added some comments in 894350f . They may need to be edited later, but should be enough for the CI for now.

@spytheman spytheman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work.

@spytheman
spytheman merged commit d7bdb72 into vlang:master Aug 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants