diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9cdfaf9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}", + "cwd": "${workspaceFolder}/examples/chat", + "console": "integratedTerminal" + } + ] +} diff --git a/examples/chat/certificates/README.md b/examples/chat/certificates/README.md new file mode 100644 index 0000000..aef3d09 --- /dev/null +++ b/examples/chat/certificates/README.md @@ -0,0 +1,26 @@ +# Certificates + +The certificates in for the examples are generated using the commands shown below. + +Note that this was run on OpenSSL 1.1.1d, of which the arguments can be found in the [OpenSSL Manpages](https://www.openssl.org/docs/man1.1.1/man1), and is not guaranteed to work on different OpenSSL versions. + +```shell +# Extensions required for certificate validation. +$ EXTFILE='extfile.conf' +$ echo 'subjectAltName = IP:127.0.0.1\nbasicConstraints = critical,CA:true' > "${EXTFILE}" + +# Server. +$ SERVER_NAME='server' +$ openssl ecparam -name prime256v1 -genkey -noout -out "${SERVER_NAME}.pem" +$ openssl req -key "${SERVER_NAME}.pem" -new -sha256 -subj '/C=NL' -out "${SERVER_NAME}.csr" +$ openssl x509 -req -in "${SERVER_NAME}.csr" -extfile "${EXTFILE}" -days 365 -signkey "${SERVER_NAME}.pem" -sha256 -out "${SERVER_NAME}.pub.pem" + +# Client. +$ CLIENT_NAME='client' +$ openssl ecparam -name prime256v1 -genkey -noout -out "${CLIENT_NAME}.pem" +$ openssl req -key "${CLIENT_NAME}.pem" -new -sha256 -subj '/C=NL' -out "${CLIENT_NAME}.csr" +$ openssl x509 -req -in "${CLIENT_NAME}.csr" -extfile "${EXTFILE}" -days 365 -CA "${SERVER_NAME}.pub.pem" -CAkey "${SERVER_NAME}.pem" -set_serial '0xabcd' -sha256 -out "${CLIENT_NAME}.pub.pem" + +# Cleanup. +$ rm "${EXTFILE}" "${SERVER_NAME}.csr" "${CLIENT_NAME}.csr" +``` diff --git a/examples/chat/certificates/client.pem b/examples/chat/certificates/client.pem new file mode 100644 index 0000000..4215b8f --- /dev/null +++ b/examples/chat/certificates/client.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIISoeP9MVCLki8cOM/hyi9/IyCZ3+fxYu+3zHJH4g1fxoAoGCCqGSM49 +AwEHoUQDQgAEQtNPp0zDJDMeoF0EVI1xKqi88b809cn5NDigDKo6ILW0J54/L3GB +LzkXygCQJxcVKsBk4OQB04nBd1TSzzfD0Q== +-----END EC PRIVATE KEY----- diff --git a/examples/chat/certificates/client.pub.pem b/examples/chat/certificates/client.pub.pem new file mode 100644 index 0000000..2aa6b9d --- /dev/null +++ b/examples/chat/certificates/client.pub.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBLTCB1aADAgECAgMAq80wCgYIKoZIzj0EAwIwDTELMAkGA1UEBhMCTkwwHhcN +MjQxMTA0MTc0MzI0WhcNMjUxMTA0MTc0MzI0WjANMQswCQYDVQQGEwJOTDBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABELTT6dMwyQzHqBdBFSNcSqovPG/NPXJ+TQ4 +oAyqOiC1tCeePy9xgS85F8oAkCcXFSrAZODkAdOJwXdU0s83w9GjJDAiMA8GA1Ud +EQQIMAaHBH8AAAEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiAw +OWA9hQ/mRt4QjaJoKm2nlWnz+fmhFKcLy4Dko8enPgIgNZbktOO2soA1TxxQJybR +XfbC0srKxi5tx+tCASwj800= +-----END CERTIFICATE----- diff --git a/examples/chat/certificates/server.pem b/examples/chat/certificates/server.pem new file mode 100644 index 0000000..67e1ece --- /dev/null +++ b/examples/chat/certificates/server.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIG+1OTeVT3v/OYSBSv5qzM8dO6RNJ8VAGelS54y00dGmoAoGCCqGSM49 +AwEHoUQDQgAEbG8/2ipiuRo8cy3S2PuNskv6vY2GNVamZYP0ZFfrAOOXpIp2WIVA +UkMogtGsnrMFqOoZSic+NfajMBcHX0C5LQ== +-----END EC PRIVATE KEY----- diff --git a/examples/chat/certificates/server.pub.pem b/examples/chat/certificates/server.pub.pem new file mode 100644 index 0000000..9fd3c30 --- /dev/null +++ b/examples/chat/certificates/server.pub.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBNTCB26ADAgECAgkA7SUbA6QFShswCgYIKoZIzj0EAwIwDTELMAkGA1UEBhMC +TkwwHhcNMjQxMTA0MTc0MjUzWhcNMjUxMTA0MTc0MjUzWjANMQswCQYDVQQGEwJO +TDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGxvP9oqYrkaPHMt0tj7jbJL+r2N +hjVWpmWD9GRX6wDjl6SKdliFQFJDKILRrJ6zBajqGUonPjX2ozAXB19AuS2jJDAi +MA8GA1UdEQQIMAaHBH8AAAEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNJ +ADBGAiEAlXkUu6xhYeicFSWW/5lVBVH09KOnXAI13dW6FaFIxl4CIQDN8jWod40y +7HpDHkJXwWPfQ9V0TPFczs/mzfMM6a2Ahg== +-----END CERTIFICATE----- diff --git a/examples/chat/client/main.go b/examples/chat/client/main.go new file mode 100644 index 0000000..c0092a0 --- /dev/null +++ b/examples/chat/client/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "crypto/x509" + "encoding/pem" + "errors" + "flag" + "fmt" + "net" + "os" + "path/filepath" + + "github.com/pion/dtls/v3/examples/util" + tls "github.com/refraction-networking/utls" +) + +func main() { + var remoteAddr = flag.String("raddr", "127.0.0.1:6666", "remote address") + flag.Parse() + + rootCertificate, err := LoadCertificate("certificates/server.pub.pem") + util.Check(err) + certPool := x509.NewCertPool() + cert, err := x509.ParseCertificate(rootCertificate.Certificate[0]) + util.Check(err) + certPool.AddCert(cert) + + dialConn, err := net.Dial("tcp", *remoteAddr) + if err != nil { + fmt.Printf("net.Dial() failed: %+v\n", err) + return + } + + config := tls.Config{ServerName: "127.0.0.1", Certificates: []tls.Certificate{*rootCertificate}, RootCAs: certPool, ClientSessionCache: tls.NewLRUClientSessionCache(2)} + tlsConn := tls.Client(dialConn, &config) + + tlsConn.Write([]byte("hi\n")) + + tlsConn.Close() + + dialConn2, err := net.Dial("tcp", *remoteAddr) + if err != nil { + fmt.Printf("net.Dial() failed: %+v\n", err) + return + } + + tlsConn2 := tls.Client(dialConn2, &config) + + util.Chat(tlsConn2) +} + +// LoadCertificate Load/read certificate(s) from file +func LoadCertificate(path string) (*tls.Certificate, error) { + rawData, err := os.ReadFile(filepath.Clean(path)) + if err != nil { + return nil, err + } + + var certificate tls.Certificate + + for { + block, rest := pem.Decode(rawData) + if block == nil { + break + } + + if block.Type != "CERTIFICATE" { + return nil, errBlockIsNotCertificate + } + + certificate.Certificate = append(certificate.Certificate, block.Bytes) + rawData = rest + } + + if len(certificate.Certificate) == 0 { + return nil, errNoCertificateFound + } + + return &certificate, nil +} + +var ( + errBlockIsNotCertificate = errors.New("block is not a certificate, unable to load certificates") + errNoCertificateFound = errors.New("no certificate found, unable to load certificates") +) diff --git a/examples/chat/server/main.go b/examples/chat/server/main.go new file mode 100644 index 0000000..d84a45c --- /dev/null +++ b/examples/chat/server/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "flag" + "net" + + "github.com/pion/dtls/v3/examples/util" + tls "github.com/refraction-networking/utls" +) + +func main() { + var listenAddr = flag.String("laddr", "127.0.0.1:6666", "listen address") + flag.Parse() + + certificate, err := tls.LoadX509KeyPair("certificates/server.pub.pem", "certificates/server.pem") + util.Check(err) + + listener, err := net.Listen("tcp", *listenAddr) + if err != nil { + panic(err.Error()) + } + + tlsListener := tls.NewListener(listener, &tls.Config{Certificates: []tls.Certificate{certificate}}) + + hub := util.NewHub() + + go func() { + for { + conn, err := tlsListener.Accept() + util.Check(err) + hub.Register(conn) + } + + }() + + hub.Chat() + +} diff --git a/go.mod b/go.mod index d73a942..5c94997 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,14 @@ require ( github.com/andybalholm/brotli v1.0.6 github.com/cloudflare/circl v1.3.7 github.com/klauspost/compress v1.17.4 - golang.org/x/crypto v0.21.0 - golang.org/x/net v0.23.0 - golang.org/x/sys v0.18.0 + golang.org/x/crypto v0.27.0 + golang.org/x/net v0.29.0 + golang.org/x/sys v0.25.0 ) -require golang.org/x/text v0.14.0 // indirect +require ( + github.com/pion/dtls/v3 v3.0.3 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + golang.org/x/text v0.18.0 // indirect +) diff --git a/go.sum b/go.sum index 231edae..7957440 100644 --- a/go.sum +++ b/go.sum @@ -4,11 +4,25 @@ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vc github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/pion/dtls/v3 v3.0.3 h1:j5ajZbQwff7Z8k3pE3S+rQ4STvKvXUdKsi/07ka+OWM= +github.com/pion/dtls/v3 v3.0.3/go.mod h1:weOTUyIV4z0bQaVzKe8kpaP17+us3yAuiQsEAG1STMU= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= diff --git a/u_handshake_oscur0.go b/u_handshake_oscur0.go new file mode 100644 index 0000000..bf8418c --- /dev/null +++ b/u_handshake_oscur0.go @@ -0,0 +1 @@ +package tls