Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to quic-go v0.15.5, adapt usage #141

Merged
merged 6 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion _examples/shttp/client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package main

import (
"crypto/tls"
"flag"
"fmt"
"io/ioutil"
Expand All @@ -38,7 +39,7 @@ func main() {

// Create a standard server with our custom RoundTripper
c := &http.Client{
Transport: shttp.NewRoundTripper(nil, nil),
Transport: shttp.NewRoundTripper(&tls.Config{InsecureSkipVerify: true}, nil),
}
// (just for demonstration on how to use Close. Clients are safe for concurrent use and should be re-used)
defer c.Transport.(shttp.RoundTripper).Close()
Expand Down
2 changes: 1 addition & 1 deletion bat/bat.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func init() {
flag.Usage = usage
flag.Parse()

defaultSetting.Transport = shttp.NewRoundTripper(nil, nil)
defaultSetting.Transport = shttp.NewRoundTripper(&tls.Config{InsecureSkipVerify: true}, nil)
}

func parsePrintOption(s string) {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ require (
github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec
github.com/kormat/fmt15 v0.0.0-20181112140556-ee69fecb2656
github.com/kr/pty v1.1.8
github.com/lucas-clemente/quic-go v0.7.1-0.20190212114006-fd7246d7ed6e
github.com/lucas-clemente/quic-go v0.15.5
github.com/mattn/go-sqlite3 v1.9.1-0.20180719091609-b3511bfdd742
github.com/msteinert/pam v0.0.0-20190215180659-f29b9f28d6f9
github.com/netsec-ethz/rains v0.1.0
github.com/scionproto/scion v0.5.0
github.com/smartystreets/goconvey v1.6.4
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
gopkg.in/alecthomas/kingpin.v2 v2.2.6
)
163 changes: 163 additions & 0 deletions go.sum

Large diffs are not rendered by default.

29 changes: 23 additions & 6 deletions netcat/modes/quic-modes.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package modes

import (
"context"
"crypto/tls"
"io"
golog "log"

Expand All @@ -24,6 +26,8 @@ import (
log "github.com/inconshreveable/log15"
)

const nextProto = "netcat"

type sessConn struct {
sess quic.Session
stream quic.Stream
Expand All @@ -43,7 +47,7 @@ func (conn *sessConn) Close() error {
return err
}

err = conn.sess.Close()
err = conn.sess.CloseWithError(quic.ErrorCode(0), "")
if err != nil {
return err
}
Expand All @@ -53,21 +57,27 @@ func (conn *sessConn) Close() error {

// DoListenQUIC listens on a QUIC socket
func DoListenQUIC(port uint16) chan io.ReadWriteCloser {
listener, err := appquic.ListenPort(port, nil, &quic.Config{KeepAlive: true})
listener, err := appquic.ListenPort(
port,
&tls.Config{
Certificates: appquic.GetDummyTLSCerts(),
NextProtos: []string{nextProto}},
&quic.Config{KeepAlive: true},
)
if err != nil {
golog.Panicf("Can't listen on port %d: %v", port, err)
}

conns := make(chan io.ReadWriteCloser)
go func() {
for {
sess, err := listener.Accept()
sess, err := listener.Accept(context.Background())
if err != nil {
log.Crit("Can't accept listener: %v", err)
continue
}

stream, err := sess.AcceptStream()
stream, err := sess.AcceptStream(context.Background())
if err != nil {
log.Crit("Can't accept stream: %v", err)
continue
Expand All @@ -87,12 +97,19 @@ func DoListenQUIC(port uint16) chan io.ReadWriteCloser {

// DoDialQUIC dials with a QUIC socket
func DoDialQUIC(remoteAddr string) io.ReadWriteCloser {
sess, err := appquic.Dial(remoteAddr, nil, &quic.Config{KeepAlive: true})
sess, err := appquic.Dial(
remoteAddr,
&tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{nextProto},
},
&quic.Config{KeepAlive: true},
)
if err != nil {
golog.Panicf("Can't dial remote address %v: %v", remoteAddr, err)
}

stream, err := sess.OpenStreamSync()
stream, err := sess.OpenStreamSync(context.Background())
if err != nil {
golog.Panicf("Can't open stream: %v", err)
}
Expand Down
93 changes: 65 additions & 28 deletions pkg/appnet/appquic/appquic.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ import (
)

var (
// Don't verify the server's cert, as we are not using the TLS PKI.
cliTLSCfg = &tls.Config{InsecureSkipVerify: true}
srvTLSCfg *tls.Config
srvTLSCfgInit sync.Once
srvTLSDummyCerts []tls.Certificate
srvTLSDummyCertsInit sync.Once
)

// closerSession is a wrapper around quic.Session that always closes the
Expand All @@ -44,9 +42,20 @@ type closerSession struct {
conn *snet.Conn
}

func (s *closerSession) Close() error {
func (s *closerSession) CloseWithError(code quic.ErrorCode, desc string) error {
s.conn.Close()
return s.Session.Close()
return s.Session.CloseWithError(code, desc)
}

// closerEarlySession is a wrapper around quic.EarlySession, analogoues to closerSession
type closerEarlySession struct {
quic.EarlySession
conn *snet.Conn
}

func (s *closerEarlySession) CloseWithError(code quic.ErrorCode, desc string) error {
s.conn.Close()
return s.EarlySession.CloseWithError(code, desc)
}

// Dial establishes a new QUIC connection to a server at the remote address.
Expand All @@ -57,34 +66,65 @@ func Dial(remote string, tlsConf *tls.Config, quicConf *quic.Config) (quic.Sessi
if err != nil {
return nil, err
}
return DialAddr(raddr, tlsConf, quicConf)
return DialAddr(raddr, remote, tlsConf, quicConf)
}

// DialAddr establishes a new QUIC connection to a server at the remote address.
//
// If no path is specified in raddr, DialAddr will choose the first available path,
// analogous to appnet.DialAddr.
func DialAddr(raddr *snet.UDPAddr, tlsConf *tls.Config, quicConf *quic.Config) (quic.Session, error) {
if raddr.Path == nil {
err := appnet.SetDefaultPath(raddr)
if err != nil {
return nil, err
}
// The host parameter is used for SNI.
// The tls.Config must define an application protocol (using NextProtos).
func DialAddr(raddr *snet.UDPAddr, host string, tlsConf *tls.Config, quicConf *quic.Config) (quic.Session, error) {
err := ensurePathDefined(raddr)
if err != nil {
return nil, err
}
sconn, err := appnet.Listen(nil)
if err != nil {
return nil, err
}
if tlsConf == nil {
tlsConf = cliTLSCfg
}
session, err := quic.Dial(sconn, raddr, "host:0", tlsConf, quicConf)
session, err := quic.Dial(sconn, raddr, host, tlsConf, quicConf)
if err != nil {
return nil, err
}
return &closerSession{session, sconn}, nil
}

// DialEarly establishes a new 0-RTT QUIC connection to a server. Analogous to Dial.
func DialEarly(remote string, tlsConf *tls.Config, quicConf *quic.Config) (quic.EarlySession, error) {
raddr, err := appnet.ResolveUDPAddr(remote)
if err != nil {
return nil, err
}
return DialAddrEarly(raddr, remote, tlsConf, quicConf)
}

// DialAddrEarly establishes a new 0-RTT QUIC connection to a server. Analogous to DialAddr.
func DialAddrEarly(raddr *snet.UDPAddr, host string, tlsConf *tls.Config, quicConf *quic.Config) (quic.EarlySession, error) {
err := ensurePathDefined(raddr)
if err != nil {
return nil, err
}
sconn, err := appnet.Listen(nil)
if err != nil {
return nil, err
}
session, err := quic.DialEarly(sconn, raddr, host, tlsConf, quicConf)
if err != nil {
return nil, err
}
// XXX(matzf): quic.DialEarly seems to have the wrong return type declared (quic.DialAddrEarly returns EarlySession)
return &closerEarlySession{session.(quic.EarlySession), sconn}, nil
}

func ensurePathDefined(raddr *snet.UDPAddr) error {
if raddr.Path == nil {
return appnet.SetDefaultPath(raddr)
}
return nil
}

// ListenPort listens for QUIC connections on a SCION/UDP port.
//
// See note on wildcard addresses in the appnet package documentation.
Expand All @@ -93,25 +133,22 @@ func ListenPort(port uint16, tlsConf *tls.Config, quicConfig *quic.Config) (quic
if err != nil {
return nil, err
}
if tlsConf == nil {
tlsConf, err = GetDummyTLSConfig()
if err != nil {
return nil, err
}
}
return quic.Listen(sconn, tlsConf, quicConfig)
}

// GetDummyTLSConfig returns the (singleton) default server TLS config with a fresh
// GetDummyTLSCert returns the singleton TLS certificate with a fresh
// private key and a dummy certificate.
func GetDummyTLSConfig() (*tls.Config, error) {
func GetDummyTLSCerts() []tls.Certificate {
var initErr error
srvTLSCfgInit.Do(func() {
srvTLSDummyCertsInit.Do(func() {
cert, err := generateKeyAndCert()
if err != nil {
initErr = fmt.Errorf("appquic: Unable to generate dummy TLS cert/key: %v", err)
}
srvTLSCfg = &tls.Config{Certificates: []tls.Certificate{*cert}}
srvTLSDummyCerts = []tls.Certificate{*cert}
})
return srvTLSCfg, initErr
if initErr != nil {
panic(initErr)
}
return srvTLSDummyCerts
}
2 changes: 1 addition & 1 deletion pkg/appnet/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
)

var addrRegexp = regexp.MustCompile(`^(\d+-[\d:A-Fa-f]+),\[([^\]]+)\]$`)
var hostPortRegexp = regexp.MustCompile(`^((?:[-.\da-zA-Z]+)|(?:\d+-[\d:A-Fa-f]+,\[[^\]]+\])):(\d+)$`)
var hostPortRegexp = regexp.MustCompile(`^((?:[-.\da-zA-Z]+)|(?:\d+-[\d:A-Fa-f]+,(\[[^\]]+\]|[^\]]+))):(\d+)$`)

const (
iaIndex = iota + 1
Expand Down
1 change: 1 addition & 0 deletions pkg/appnet/hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ func TestSplitHostPort(t *testing.T) {
}
cases := []testCase{
{"1-ff00:0:0,[1.1.1.1]:80", "1-ff00:0:0,[1.1.1.1]", "80", false},
{"1-ff00:0:0,1.1.1.1:80", "1-ff00:0:0,1.1.1.1", "80", false},
{"1-ff00:0:0,[::]:80", "1-ff00:0:0,[::]", "80", false},
{"foo:80", "foo", "80", false},
{"www.example.com:666", "www.example.com", "666", false},
Expand Down
20 changes: 10 additions & 10 deletions pkg/shttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
package shttp

import (
"crypto/tls"
"net"
"net/http"

"github.com/lucas-clemente/quic-go/h2quic"
"github.com/lucas-clemente/quic-go/http3"
"github.com/netsec-ethz/scion-apps/pkg/appnet"
"github.com/netsec-ethz/scion-apps/pkg/appnet/appquic"
)

// Server wraps a h2quic.Server making it work with SCION
// Server wraps a http3.Server making it work with SCION
type Server struct {
*h2quic.Server
*http3.Server
}

// ListenAndServe listens for HTTPS connections on the SCION address addr and calls Serve
// with handler to handle requests
func ListenAndServe(addr string, handler http.Handler) error {

scionServer := &Server{
Server: &h2quic.Server{
Server: &http3.Server{
Server: &http.Server{
Addr: addr,
Handler: handler,
Expand All @@ -48,7 +49,7 @@ func ListenAndServe(addr string, handler http.Handler) error {
func Serve(conn net.PacketConn, handler http.Handler) error {

scionServer := &Server{
Server: &h2quic.Server{
Server: &http3.Server{
Server: &http.Server{
Handler: handler,
},
Expand Down Expand Up @@ -79,11 +80,10 @@ func (srv *Server) Serve(conn net.PacketConn) error {

// set dummy TLS config if not set:
if srv.TLSConfig == nil {
cfg, err := appquic.GetDummyTLSConfig()
if err != nil {
return err
}
srv.TLSConfig = cfg
srv.TLSConfig = &tls.Config{}
}
if len(srv.TLSConfig.Certificates) == 0 {
srv.TLSConfig.Certificates = appquic.GetDummyTLSCerts()
}

return srv.Server.Serve(conn)
Expand Down
16 changes: 8 additions & 8 deletions pkg/shttp/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"strconv"

"github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/h2quic"
"github.com/lucas-clemente/quic-go/http3"
"github.com/netsec-ethz/scion-apps/pkg/appnet/appquic"
"github.com/scionproto/scion/go/lib/snet"
)
Expand All @@ -43,7 +43,7 @@ type RoundTripper interface {
// of an http.Client.
func NewRoundTripper(tlsClientCfg *tls.Config, quicCfg *quic.Config) RoundTripper {
return &roundTripper{
&h2quic.RoundTripper{
&http3.RoundTripper{
Dial: dial,
QuicConfig: quicCfg,
TLSClientConfig: tlsClientCfg,
Expand All @@ -54,16 +54,16 @@ func NewRoundTripper(tlsClientCfg *tls.Config, quicCfg *quic.Config) RoundTrippe
var _ RoundTripper = (*roundTripper)(nil)

// roundTripper implements the RoundTripper interface. It wraps a
// h2quic.RoundTripper, making it compatible with SCION
// http3.RoundTripper, making it compatible with SCION
type roundTripper struct {
rt *h2quic.RoundTripper
rt *http3.RoundTripper
}

// RoundTrip does a single round trip; retreiving a response for a given request
func (t *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {

// If req.URL.Host is a SCION address, we need to mangle it so it passes through
// h2quic without tripping up.
// http3 without tripping up.
// Note: when using the http.Client, the URL must already arrive mangled
// here, otherwise it would not have parsed.
cpy := *req
Expand All @@ -85,8 +85,8 @@ func (t *roundTripper) Close() (err error) {
}

// dial is the Dial function used in RoundTripper
func dial(network, address string, tlsCfg *tls.Config, cfg *quic.Config) (quic.Session, error) {
return appquic.Dial(unmangleSCIONAddr(address), tlsCfg, cfg)
func dial(network, address string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
return appquic.DialEarly(unmangleSCIONAddr(address), tlsCfg, cfg)
}

var scionAddrURLRegexp = regexp.MustCompile(
Expand Down Expand Up @@ -136,7 +136,7 @@ func mangleSCIONAddr(address string) string {
// This parses the address, so that it can safely join host and port, with the
// brackets in the right place. Yes, this means this will be parsed twice.
//
// Assumes that address always has a port (this is enforced by the h2quic
// Assumes that address always has a port (this is enforced by the http3
// roundtripper code)
func unmangleSCIONAddr(address string) string {
host, port, err := net.SplitHostPort(address)
Expand Down
Loading