mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 20:57:36 +03:00
name the quic.Cookie to quic.Token
This commit is contained in:
parent
06da72ae4e
commit
1d6707325f
12 changed files with 234 additions and 232 deletions
|
@ -3,6 +3,7 @@
|
||||||
## v0.12.0 (unreleased)
|
## v0.12.0 (unreleased)
|
||||||
|
|
||||||
- Implement HTTP/3.
|
- Implement HTTP/3.
|
||||||
|
- Rename `quic.Cookie` to `quic.Token` and `quic.Config.AcceptCookie` to `quic.Config.AcceptToken`.
|
||||||
|
|
||||||
## v0.11.0 (2019-04-05)
|
## v0.11.0 (2019-04-05)
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,8 @@ var _ = Describe("Handshake RTT tests", func() {
|
||||||
expectDurationInRTTs(2)
|
expectDurationInRTTs(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("establishes a connection in 1 RTT when the server doesn't require a Cookie", func() {
|
It("establishes a connection in 1 RTT when the server doesn't require a token", func() {
|
||||||
serverConfig.AcceptCookie = func(_ net.Addr, _ *quic.Cookie) bool {
|
serverConfig.AcceptToken = func(_ net.Addr, _ *quic.Token) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
runServerAndProxy()
|
runServerAndProxy()
|
||||||
|
@ -128,7 +128,7 @@ var _ = Describe("Handshake RTT tests", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("establishes a connection in 2 RTTs if a HelloRetryRequest is performed", func() {
|
It("establishes a connection in 2 RTTs if a HelloRetryRequest is performed", func() {
|
||||||
serverConfig.AcceptCookie = func(_ net.Addr, _ *quic.Cookie) bool {
|
serverConfig.AcceptToken = func(_ net.Addr, _ *quic.Token) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
serverTLSConfig.CurvePreferences = []tls.CurveID{tls.CurveP384}
|
serverTLSConfig.CurvePreferences = []tls.CurveID{tls.CurveP384}
|
||||||
|
@ -142,8 +142,8 @@ var _ = Describe("Handshake RTT tests", func() {
|
||||||
expectDurationInRTTs(2)
|
expectDurationInRTTs(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("doesn't complete the handshake when the server never accepts the Cookie", func() {
|
It("doesn't complete the handshake when the server never accepts the token", func() {
|
||||||
serverConfig.AcceptCookie = func(_ net.Addr, _ *quic.Cookie) bool {
|
serverConfig.AcceptToken = func(_ net.Addr, _ *quic.Token) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
clientConfig.HandshakeTimeout = 500 * time.Millisecond
|
clientConfig.HandshakeTimeout = 500 * time.Millisecond
|
||||||
|
|
|
@ -196,7 +196,7 @@ var _ = Describe("Handshake tests", func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
serverConfig.AcceptCookie = func(net.Addr, *quic.Cookie) bool { return true }
|
serverConfig.AcceptToken = func(net.Addr, *quic.Token) bool { return true }
|
||||||
var err error
|
var err error
|
||||||
// start the server, but don't call Accept
|
// start the server, but don't call Accept
|
||||||
server, err = quic.ListenAddr("localhost:0", testdata.GetTLSConfig(), serverConfig)
|
server, err = quic.ListenAddr("localhost:0", testdata.GetTLSConfig(), serverConfig)
|
||||||
|
|
12
interface.go
12
interface.go
|
@ -16,8 +16,8 @@ type StreamID = protocol.StreamID
|
||||||
// A VersionNumber is a QUIC version number.
|
// A VersionNumber is a QUIC version number.
|
||||||
type VersionNumber = protocol.VersionNumber
|
type VersionNumber = protocol.VersionNumber
|
||||||
|
|
||||||
// A Cookie can be used to verify the ownership of the client address.
|
// A Token can be used to verify the ownership of the client address.
|
||||||
type Cookie struct {
|
type Token struct {
|
||||||
RemoteAddr string
|
RemoteAddr string
|
||||||
SentTime time.Time
|
SentTime time.Time
|
||||||
}
|
}
|
||||||
|
@ -187,11 +187,11 @@ type Config struct {
|
||||||
// If the timeout is exceeded, the connection is closed.
|
// If the timeout is exceeded, the connection is closed.
|
||||||
// If this value is zero, the timeout is set to 30 seconds.
|
// If this value is zero, the timeout is set to 30 seconds.
|
||||||
IdleTimeout time.Duration
|
IdleTimeout time.Duration
|
||||||
// AcceptCookie determines if a Cookie is accepted.
|
// AcceptToken determines if a Token is accepted.
|
||||||
// It is called with cookie = nil if the client didn't send an Cookie.
|
// It is called with token = nil if the client didn't send a token.
|
||||||
// If not set, it verifies that the address matches, and that the Cookie was issued within the last 24 hours.
|
// If not set, it verifies that the address matches, and that the token was issued within the last 24 hours.
|
||||||
// This option is only valid for the server.
|
// This option is only valid for the server.
|
||||||
AcceptCookie func(clientAddr net.Addr, cookie *Cookie) bool
|
AcceptToken func(clientAddr net.Addr, token *Token) bool
|
||||||
// MaxReceiveStreamFlowControlWindow is the maximum stream-level flow control window for receiving data.
|
// MaxReceiveStreamFlowControlWindow is the maximum stream-level flow control window for receiving data.
|
||||||
// If this value is zero, it will default to 1 MB for the server and 6 MB for the client.
|
// If this value is zero, it will default to 1 MB for the server and 6 MB for the client.
|
||||||
MaxReceiveStreamFlowControlWindow uint64
|
MaxReceiveStreamFlowControlWindow uint64
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
package handshake
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/asn1"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
cookiePrefixIP byte = iota
|
|
||||||
cookiePrefixString
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Cookie is derived from the client address and can be used to verify the ownership of this address.
|
|
||||||
type Cookie struct {
|
|
||||||
RemoteAddr string
|
|
||||||
OriginalDestConnectionID protocol.ConnectionID
|
|
||||||
// The time that the Cookie was issued (resolution 1 second)
|
|
||||||
SentTime time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// token is the struct that is used for ASN1 serialization and deserialization
|
|
||||||
type token struct {
|
|
||||||
RemoteAddr []byte
|
|
||||||
OriginalDestConnectionID []byte
|
|
||||||
|
|
||||||
Timestamp int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// A CookieGenerator generates Cookies
|
|
||||||
type CookieGenerator struct {
|
|
||||||
cookieProtector cookieProtector
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCookieGenerator initializes a new CookieGenerator
|
|
||||||
func NewCookieGenerator() (*CookieGenerator, error) {
|
|
||||||
cookieProtector, err := newCookieProtector()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &CookieGenerator{
|
|
||||||
cookieProtector: cookieProtector,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewToken generates a new Cookie for a given source address
|
|
||||||
func (g *CookieGenerator) NewToken(raddr net.Addr, origConnID protocol.ConnectionID) ([]byte, error) {
|
|
||||||
data, err := asn1.Marshal(token{
|
|
||||||
RemoteAddr: encodeRemoteAddr(raddr),
|
|
||||||
OriginalDestConnectionID: origConnID,
|
|
||||||
Timestamp: time.Now().Unix(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return g.cookieProtector.NewToken(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeToken decodes a Cookie
|
|
||||||
func (g *CookieGenerator) DecodeToken(encrypted []byte) (*Cookie, error) {
|
|
||||||
// if the client didn't send any Cookie, DecodeToken will be called with a nil-slice
|
|
||||||
if len(encrypted) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := g.cookieProtector.DecodeToken(encrypted)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t := &token{}
|
|
||||||
rest, err := asn1.Unmarshal(data, t)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rest) != 0 {
|
|
||||||
return nil, fmt.Errorf("rest when unpacking token: %d", len(rest))
|
|
||||||
}
|
|
||||||
cookie := &Cookie{
|
|
||||||
RemoteAddr: decodeRemoteAddr(t.RemoteAddr),
|
|
||||||
SentTime: time.Unix(t.Timestamp, 0),
|
|
||||||
}
|
|
||||||
if len(t.OriginalDestConnectionID) > 0 {
|
|
||||||
cookie.OriginalDestConnectionID = protocol.ConnectionID(t.OriginalDestConnectionID)
|
|
||||||
}
|
|
||||||
return cookie, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodeRemoteAddr encodes a remote address such that it can be saved in the Cookie
|
|
||||||
func encodeRemoteAddr(remoteAddr net.Addr) []byte {
|
|
||||||
if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok {
|
|
||||||
return append([]byte{cookiePrefixIP}, udpAddr.IP...)
|
|
||||||
}
|
|
||||||
return append([]byte{cookiePrefixString}, []byte(remoteAddr.String())...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodeRemoteAddr decodes the remote address saved in the Cookie
|
|
||||||
func decodeRemoteAddr(data []byte) string {
|
|
||||||
// data will never be empty for a Cookie that we generated. Check it to be on the safe side
|
|
||||||
if len(data) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if data[0] == cookiePrefixIP {
|
|
||||||
return net.IP(data[1:]).String()
|
|
||||||
}
|
|
||||||
return string(data[1:])
|
|
||||||
}
|
|
110
internal/handshake/token_generator.go
Normal file
110
internal/handshake/token_generator.go
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package handshake
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/asn1"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
tokenPrefixIP byte = iota
|
||||||
|
tokenPrefixString
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Token is derived from the client address and can be used to verify the ownership of this address.
|
||||||
|
type Token struct {
|
||||||
|
RemoteAddr string
|
||||||
|
OriginalDestConnectionID protocol.ConnectionID
|
||||||
|
// The time that the Token was issued (resolution 1 second)
|
||||||
|
SentTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// token is the struct that is used for ASN1 serialization and deserialization
|
||||||
|
type token struct {
|
||||||
|
RemoteAddr []byte
|
||||||
|
OriginalDestConnectionID []byte
|
||||||
|
|
||||||
|
Timestamp int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TokenGenerator generates tokens
|
||||||
|
type TokenGenerator struct {
|
||||||
|
tokenProtector tokenProtector
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTokenGenerator initializes a new TookenGenerator
|
||||||
|
func NewTokenGenerator() (*TokenGenerator, error) {
|
||||||
|
tokenProtector, err := newTokenProtector()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TokenGenerator{
|
||||||
|
tokenProtector: tokenProtector,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewToken generates a new token for a given source address
|
||||||
|
func (g *TokenGenerator) NewToken(raddr net.Addr, origConnID protocol.ConnectionID) ([]byte, error) {
|
||||||
|
data, err := asn1.Marshal(token{
|
||||||
|
RemoteAddr: encodeRemoteAddr(raddr),
|
||||||
|
OriginalDestConnectionID: origConnID,
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return g.tokenProtector.NewToken(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeToken decodes a token
|
||||||
|
func (g *TokenGenerator) DecodeToken(encrypted []byte) (*Token, error) {
|
||||||
|
// if the client didn't send any token, DecodeToken will be called with a nil-slice
|
||||||
|
if len(encrypted) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := g.tokenProtector.DecodeToken(encrypted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t := &token{}
|
||||||
|
rest, err := asn1.Unmarshal(data, t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rest) != 0 {
|
||||||
|
return nil, fmt.Errorf("rest when unpacking token: %d", len(rest))
|
||||||
|
}
|
||||||
|
token := &Token{
|
||||||
|
RemoteAddr: decodeRemoteAddr(t.RemoteAddr),
|
||||||
|
SentTime: time.Unix(t.Timestamp, 0),
|
||||||
|
}
|
||||||
|
if len(t.OriginalDestConnectionID) > 0 {
|
||||||
|
token.OriginalDestConnectionID = protocol.ConnectionID(t.OriginalDestConnectionID)
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeRemoteAddr encodes a remote address such that it can be saved in the token
|
||||||
|
func encodeRemoteAddr(remoteAddr net.Addr) []byte {
|
||||||
|
if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok {
|
||||||
|
return append([]byte{tokenPrefixIP}, udpAddr.IP...)
|
||||||
|
}
|
||||||
|
return append([]byte{tokenPrefixString}, []byte(remoteAddr.String())...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeRemoteAddr decodes the remote address saved in the token
|
||||||
|
func decodeRemoteAddr(data []byte) string {
|
||||||
|
// data will never be empty for a token that we generated.
|
||||||
|
// Check it to be on the safe side
|
||||||
|
if len(data) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if data[0] == tokenPrefixIP {
|
||||||
|
return net.IP(data[1:]).String()
|
||||||
|
}
|
||||||
|
return string(data[1:])
|
||||||
|
}
|
|
@ -11,64 +11,64 @@ import (
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Cookie Generator", func() {
|
var _ = Describe("Token Generator", func() {
|
||||||
var cookieGen *CookieGenerator
|
var tokenGen *TokenGenerator
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
var err error
|
var err error
|
||||||
cookieGen, err = NewCookieGenerator()
|
tokenGen, err = NewTokenGenerator()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("generates a Cookie", func() {
|
It("generates a token", func() {
|
||||||
ip := net.IPv4(127, 0, 0, 1)
|
ip := net.IPv4(127, 0, 0, 1)
|
||||||
token, err := cookieGen.NewToken(&net.UDPAddr{IP: ip, Port: 1337}, nil)
|
token, err := tokenGen.NewToken(&net.UDPAddr{IP: ip, Port: 1337}, nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(token).ToNot(BeEmpty())
|
Expect(token).ToNot(BeEmpty())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("works with nil tokens", func() {
|
It("works with nil tokens", func() {
|
||||||
cookie, err := cookieGen.DecodeToken(nil)
|
token, err := tokenGen.DecodeToken(nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(cookie).To(BeNil())
|
Expect(token).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("accepts a valid cookie", func() {
|
It("accepts a valid token", func() {
|
||||||
ip := net.IPv4(192, 168, 0, 1)
|
ip := net.IPv4(192, 168, 0, 1)
|
||||||
token, err := cookieGen.NewToken(
|
tokenEnc, err := tokenGen.NewToken(
|
||||||
&net.UDPAddr{IP: ip, Port: 1337},
|
&net.UDPAddr{IP: ip, Port: 1337},
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cookie, err := cookieGen.DecodeToken(token)
|
token, err := tokenGen.DecodeToken(tokenEnc)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(cookie.RemoteAddr).To(Equal("192.168.0.1"))
|
Expect(token.RemoteAddr).To(Equal("192.168.0.1"))
|
||||||
// the time resolution of the Cookie is just 1 second
|
// the time resolution of the token is just 1 second
|
||||||
// if Cookie generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
// if token generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
||||||
Expect(cookie.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
Expect(token.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
||||||
Expect(cookie.OriginalDestConnectionID).To(BeNil())
|
Expect(token.OriginalDestConnectionID).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("saves the connection ID", func() {
|
It("saves the connection ID", func() {
|
||||||
token, err := cookieGen.NewToken(
|
tokenEnc, err := tokenGen.NewToken(
|
||||||
&net.UDPAddr{},
|
&net.UDPAddr{},
|
||||||
protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
|
protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
|
||||||
)
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cookie, err := cookieGen.DecodeToken(token)
|
token, err := tokenGen.DecodeToken(tokenEnc)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(cookie.OriginalDestConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}))
|
Expect(token.OriginalDestConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects invalid tokens", func() {
|
It("rejects invalid tokens", func() {
|
||||||
_, err := cookieGen.DecodeToken([]byte("invalid token"))
|
_, err := tokenGen.DecodeToken([]byte("invalid token"))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects tokens that cannot be decoded", func() {
|
It("rejects tokens that cannot be decoded", func() {
|
||||||
token, err := cookieGen.cookieProtector.NewToken([]byte("foobar"))
|
token, err := tokenGen.tokenProtector.NewToken([]byte("foobar"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = cookieGen.DecodeToken(token)
|
_, err = tokenGen.DecodeToken(token)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ var _ = Describe("Cookie Generator", func() {
|
||||||
t, err := asn1.Marshal(token{RemoteAddr: []byte("foobar")})
|
t, err := asn1.Marshal(token{RemoteAddr: []byte("foobar")})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
t = append(t, []byte("rest")...)
|
t = append(t, []byte("rest")...)
|
||||||
enc, err := cookieGen.cookieProtector.NewToken(t)
|
enc, err := tokenGen.tokenProtector.NewToken(t)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = cookieGen.DecodeToken(enc)
|
_, err = tokenGen.DecodeToken(enc)
|
||||||
Expect(err).To(MatchError("rest when unpacking token: 4"))
|
Expect(err).To(MatchError("rest when unpacking token: 4"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -86,9 +86,9 @@ var _ = Describe("Cookie Generator", func() {
|
||||||
It("doesn't panic if a tokens has no data", func() {
|
It("doesn't panic if a tokens has no data", func() {
|
||||||
t, err := asn1.Marshal(token{RemoteAddr: []byte("")})
|
t, err := asn1.Marshal(token{RemoteAddr: []byte("")})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
enc, err := cookieGen.cookieProtector.NewToken(t)
|
enc, err := tokenGen.tokenProtector.NewToken(t)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = cookieGen.DecodeToken(enc)
|
_, err = tokenGen.DecodeToken(enc)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -103,26 +103,26 @@ var _ = Describe("Cookie Generator", func() {
|
||||||
ip := net.ParseIP(addr)
|
ip := net.ParseIP(addr)
|
||||||
Expect(ip).ToNot(BeNil())
|
Expect(ip).ToNot(BeNil())
|
||||||
raddr := &net.UDPAddr{IP: ip, Port: 1337}
|
raddr := &net.UDPAddr{IP: ip, Port: 1337}
|
||||||
token, err := cookieGen.NewToken(raddr, nil)
|
tokenEnc, err := tokenGen.NewToken(raddr, nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cookie, err := cookieGen.DecodeToken(token)
|
token, err := tokenGen.DecodeToken(tokenEnc)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(cookie.RemoteAddr).To(Equal(ip.String()))
|
Expect(token.RemoteAddr).To(Equal(ip.String()))
|
||||||
// the time resolution of the Cookie is just 1 second
|
// the time resolution of the token is just 1 second
|
||||||
// if Cookie generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
// if token generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
||||||
Expect(cookie.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
Expect(token.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("uses the string representation an address that is not a UDP address", func() {
|
It("uses the string representation an address that is not a UDP address", func() {
|
||||||
raddr := &net.TCPAddr{IP: net.IPv4(192, 168, 13, 37), Port: 1337}
|
raddr := &net.TCPAddr{IP: net.IPv4(192, 168, 13, 37), Port: 1337}
|
||||||
token, err := cookieGen.NewToken(raddr, nil)
|
tokenEnc, err := tokenGen.NewToken(raddr, nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cookie, err := cookieGen.DecodeToken(token)
|
token, err := tokenGen.DecodeToken(tokenEnc)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(cookie.RemoteAddr).To(Equal("192.168.13.37:1337"))
|
Expect(token.RemoteAddr).To(Equal("192.168.13.37:1337"))
|
||||||
// the time resolution of the Cookie is just 1 second
|
// the time resolution of the token is just 1 second
|
||||||
// if Cookie generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
// if token generation and this check happen in "different seconds", the difference will be between 1 and 2 seconds
|
||||||
Expect(cookie.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
Expect(token.SentTime).To(BeTemporally("~", time.Now(), 2*time.Second))
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CookieProtector is used to create and verify a cookie
|
// TokenProtector is used to create and verify a token
|
||||||
type cookieProtector interface {
|
type tokenProtector interface {
|
||||||
// NewToken creates a new token
|
// NewToken creates a new token
|
||||||
NewToken([]byte) ([]byte, error)
|
NewToken([]byte) ([]byte, error)
|
||||||
// DecodeToken decodes a token
|
// DecodeToken decodes a token
|
||||||
|
@ -20,27 +20,27 @@ type cookieProtector interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cookieSecretSize = 32
|
tokenSecretSize = 32
|
||||||
cookieNonceSize = 32
|
tokenNonceSize = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// cookieProtector is used to create and verify a cookie
|
// tokenProtector is used to create and verify a token
|
||||||
type cookieProtectorImpl struct {
|
type tokenProtectorImpl struct {
|
||||||
secret []byte
|
secret []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCookieProtector creates a source for source address tokens
|
// newTokenProtector creates a source for source address tokens
|
||||||
func newCookieProtector() (cookieProtector, error) {
|
func newTokenProtector() (tokenProtector, error) {
|
||||||
secret := make([]byte, cookieSecretSize)
|
secret := make([]byte, tokenSecretSize)
|
||||||
if _, err := rand.Read(secret); err != nil {
|
if _, err := rand.Read(secret); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &cookieProtectorImpl{secret: secret}, nil
|
return &tokenProtectorImpl{secret: secret}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewToken encodes data into a new token.
|
// NewToken encodes data into a new token.
|
||||||
func (s *cookieProtectorImpl) NewToken(data []byte) ([]byte, error) {
|
func (s *tokenProtectorImpl) NewToken(data []byte) ([]byte, error) {
|
||||||
nonce := make([]byte, cookieNonceSize)
|
nonce := make([]byte, tokenNonceSize)
|
||||||
if _, err := rand.Read(nonce); err != nil {
|
if _, err := rand.Read(nonce); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -52,20 +52,20 @@ func (s *cookieProtectorImpl) NewToken(data []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeToken decodes a token.
|
// DecodeToken decodes a token.
|
||||||
func (s *cookieProtectorImpl) DecodeToken(p []byte) ([]byte, error) {
|
func (s *tokenProtectorImpl) DecodeToken(p []byte) ([]byte, error) {
|
||||||
if len(p) < cookieNonceSize {
|
if len(p) < tokenNonceSize {
|
||||||
return nil, fmt.Errorf("Token too short: %d", len(p))
|
return nil, fmt.Errorf("Token too short: %d", len(p))
|
||||||
}
|
}
|
||||||
nonce := p[:cookieNonceSize]
|
nonce := p[:tokenNonceSize]
|
||||||
aead, aeadNonce, err := s.createAEAD(nonce)
|
aead, aeadNonce, err := s.createAEAD(nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return aead.Open(nil, aeadNonce, p[cookieNonceSize:], nil)
|
return aead.Open(nil, aeadNonce, p[tokenNonceSize:], nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *cookieProtectorImpl) createAEAD(nonce []byte) (cipher.AEAD, []byte, error) {
|
func (s *tokenProtectorImpl) createAEAD(nonce []byte) (cipher.AEAD, []byte, error) {
|
||||||
h := hkdf.New(sha256.New, s.secret, nonce, []byte("quic-go cookie source"))
|
h := hkdf.New(sha256.New, s.secret, nonce, []byte("quic-go token source"))
|
||||||
key := make([]byte, 32) // use a 32 byte key, in order to select AES-256
|
key := make([]byte, 32) // use a 32 byte key, in order to select AES-256
|
||||||
if _, err := io.ReadFull(h, key); err != nil {
|
if _, err := io.ReadFull(h, key); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
|
@ -5,35 +5,35 @@ import (
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Cookie Protector", func() {
|
var _ = Describe("Token Protector", func() {
|
||||||
var cp cookieProtector
|
var tp tokenProtector
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
var err error
|
var err error
|
||||||
cp, err = newCookieProtector()
|
tp, err = newTokenProtector()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("encodes and decodes tokens", func() {
|
It("encodes and decodes tokens", func() {
|
||||||
token, err := cp.NewToken([]byte("foobar"))
|
token, err := tp.NewToken([]byte("foobar"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(token).ToNot(ContainSubstring("foobar"))
|
Expect(token).ToNot(ContainSubstring("foobar"))
|
||||||
decoded, err := cp.DecodeToken(token)
|
decoded, err := tp.DecodeToken(token)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(decoded).To(Equal([]byte("foobar")))
|
Expect(decoded).To(Equal([]byte("foobar")))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("fails deconding invalid tokens", func() {
|
It("fails deconding invalid tokens", func() {
|
||||||
token, err := cp.NewToken([]byte("foobar"))
|
token, err := tp.NewToken([]byte("foobar"))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
token = token[1:] // remove the first byte
|
token = token[1:] // remove the first byte
|
||||||
_, err = cp.DecodeToken(token)
|
_, err = tp.DecodeToken(token)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("message authentication failed"))
|
Expect(err.Error()).To(ContainSubstring("message authentication failed"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("errors when decoding too short tokens", func() {
|
It("errors when decoding too short tokens", func() {
|
||||||
_, err := cp.DecodeToken([]byte("foobar"))
|
_, err := tp.DecodeToken([]byte("foobar"))
|
||||||
Expect(err).To(MatchError("Token too short: 6"))
|
Expect(err).To(MatchError("Token too short: 6"))
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -57,8 +57,8 @@ const MaxTrackedSkippedPackets = 10
|
||||||
// If the queue is full, new connection attempts will be rejected.
|
// If the queue is full, new connection attempts will be rejected.
|
||||||
const MaxAcceptQueueSize = 32
|
const MaxAcceptQueueSize = 32
|
||||||
|
|
||||||
// CookieExpiryTime is the valid time of a cookie
|
// TokenExpiryTime is the valid time of a token
|
||||||
const CookieExpiryTime = 24 * time.Hour
|
const TokenExpiryTime = 24 * time.Hour
|
||||||
|
|
||||||
// MaxOutstandingSentPackets is maximum number of packets saved for retransmission.
|
// MaxOutstandingSentPackets is maximum number of packets saved for retransmission.
|
||||||
// When reached, it imposes a soft limit on sending new packets:
|
// When reached, it imposes a soft limit on sending new packets:
|
||||||
|
|
32
server.go
32
server.go
|
@ -84,7 +84,7 @@ type server struct {
|
||||||
// If it is started with Listen, we take a packet conn as a parameter.
|
// If it is started with Listen, we take a packet conn as a parameter.
|
||||||
createdPacketConn bool
|
createdPacketConn bool
|
||||||
|
|
||||||
cookieGenerator *handshake.CookieGenerator
|
tokenGenerator *handshake.TokenGenerator
|
||||||
|
|
||||||
sessionHandler packetHandlerManager
|
sessionHandler packetHandlerManager
|
||||||
|
|
||||||
|
@ -186,19 +186,19 @@ func (s *server) setup() error {
|
||||||
}()
|
}()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cookieGenerator, err := handshake.NewCookieGenerator()
|
tokenGenerator, err := handshake.NewTokenGenerator()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.cookieGenerator = cookieGenerator
|
s.tokenGenerator = tokenGenerator
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultAcceptCookie = func(clientAddr net.Addr, cookie *Cookie) bool {
|
var defaultAcceptToken = func(clientAddr net.Addr, token *Token) bool {
|
||||||
if cookie == nil {
|
if token == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if time.Now().After(cookie.SentTime.Add(protocol.CookieExpiryTime)) {
|
if time.Now().After(token.SentTime.Add(protocol.TokenExpiryTime)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var sourceAddr string
|
var sourceAddr string
|
||||||
|
@ -207,7 +207,7 @@ var defaultAcceptCookie = func(clientAddr net.Addr, cookie *Cookie) bool {
|
||||||
} else {
|
} else {
|
||||||
sourceAddr = clientAddr.String()
|
sourceAddr = clientAddr.String()
|
||||||
}
|
}
|
||||||
return sourceAddr == cookie.RemoteAddr
|
return sourceAddr == token.RemoteAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// populateServerConfig populates fields in the quic.Config with their default values, if none are set
|
// populateServerConfig populates fields in the quic.Config with their default values, if none are set
|
||||||
|
@ -221,9 +221,9 @@ func populateServerConfig(config *Config) *Config {
|
||||||
versions = protocol.SupportedVersions
|
versions = protocol.SupportedVersions
|
||||||
}
|
}
|
||||||
|
|
||||||
vsa := defaultAcceptCookie
|
verifyToken := defaultAcceptToken
|
||||||
if config.AcceptCookie != nil {
|
if config.AcceptToken != nil {
|
||||||
vsa = config.AcceptCookie
|
verifyToken = config.AcceptToken
|
||||||
}
|
}
|
||||||
|
|
||||||
handshakeTimeout := protocol.DefaultHandshakeTimeout
|
handshakeTimeout := protocol.DefaultHandshakeTimeout
|
||||||
|
@ -264,7 +264,7 @@ func populateServerConfig(config *Config) *Config {
|
||||||
Versions: versions,
|
Versions: versions,
|
||||||
HandshakeTimeout: handshakeTimeout,
|
HandshakeTimeout: handshakeTimeout,
|
||||||
IdleTimeout: idleTimeout,
|
IdleTimeout: idleTimeout,
|
||||||
AcceptCookie: vsa,
|
AcceptToken: verifyToken,
|
||||||
KeepAlive: config.KeepAlive,
|
KeepAlive: config.KeepAlive,
|
||||||
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
|
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
|
||||||
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
|
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
|
||||||
|
@ -381,19 +381,19 @@ func (s *server) handleInitialImpl(p *receivedPacket, hdr *wire.Header) (quicSes
|
||||||
return nil, nil, errors.New("too short connection ID")
|
return nil, nil, errors.New("too short connection ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
var cookie *Cookie
|
var token *Token
|
||||||
var origDestConnectionID protocol.ConnectionID
|
var origDestConnectionID protocol.ConnectionID
|
||||||
if len(hdr.Token) > 0 {
|
if len(hdr.Token) > 0 {
|
||||||
c, err := s.cookieGenerator.DecodeToken(hdr.Token)
|
c, err := s.tokenGenerator.DecodeToken(hdr.Token)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cookie = &Cookie{
|
token = &Token{
|
||||||
RemoteAddr: c.RemoteAddr,
|
RemoteAddr: c.RemoteAddr,
|
||||||
SentTime: c.SentTime,
|
SentTime: c.SentTime,
|
||||||
}
|
}
|
||||||
origDestConnectionID = c.OriginalDestConnectionID
|
origDestConnectionID = c.OriginalDestConnectionID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !s.config.AcceptCookie(p.remoteAddr, cookie) {
|
if !s.config.AcceptToken(p.remoteAddr, token) {
|
||||||
// Log the Initial packet now.
|
// Log the Initial packet now.
|
||||||
// If no Retry is sent, the packet will be logged by the session.
|
// If no Retry is sent, the packet will be logged by the session.
|
||||||
(&wire.ExtendedHeader{Header: *hdr}).Log(s.logger)
|
(&wire.ExtendedHeader{Header: *hdr}).Log(s.logger)
|
||||||
|
@ -468,7 +468,7 @@ func (s *server) createNewSession(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
|
func (s *server) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
|
||||||
token, err := s.cookieGenerator.NewToken(remoteAddr, hdr.DestConnectionID)
|
token, err := s.tokenGenerator.NewToken(remoteAddr, hdr.DestConnectionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ var _ = Describe("Server", func() {
|
||||||
Expect(server.config.Versions).To(Equal(protocol.SupportedVersions))
|
Expect(server.config.Versions).To(Equal(protocol.SupportedVersions))
|
||||||
Expect(server.config.HandshakeTimeout).To(Equal(protocol.DefaultHandshakeTimeout))
|
Expect(server.config.HandshakeTimeout).To(Equal(protocol.DefaultHandshakeTimeout))
|
||||||
Expect(server.config.IdleTimeout).To(Equal(protocol.DefaultIdleTimeout))
|
Expect(server.config.IdleTimeout).To(Equal(protocol.DefaultIdleTimeout))
|
||||||
Expect(reflect.ValueOf(server.config.AcceptCookie)).To(Equal(reflect.ValueOf(defaultAcceptCookie)))
|
Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(defaultAcceptToken)))
|
||||||
Expect(server.config.KeepAlive).To(BeFalse())
|
Expect(server.config.KeepAlive).To(BeFalse())
|
||||||
// stop the listener
|
// stop the listener
|
||||||
Expect(ln.Close()).To(Succeed())
|
Expect(ln.Close()).To(Succeed())
|
||||||
|
@ -77,10 +77,10 @@ var _ = Describe("Server", func() {
|
||||||
|
|
||||||
It("setups with the right values", func() {
|
It("setups with the right values", func() {
|
||||||
supportedVersions := []protocol.VersionNumber{protocol.VersionTLS}
|
supportedVersions := []protocol.VersionNumber{protocol.VersionTLS}
|
||||||
acceptCookie := func(_ net.Addr, _ *Cookie) bool { return true }
|
acceptToken := func(_ net.Addr, _ *Token) bool { return true }
|
||||||
config := Config{
|
config := Config{
|
||||||
Versions: supportedVersions,
|
Versions: supportedVersions,
|
||||||
AcceptCookie: acceptCookie,
|
AcceptToken: acceptToken,
|
||||||
HandshakeTimeout: 1337 * time.Hour,
|
HandshakeTimeout: 1337 * time.Hour,
|
||||||
IdleTimeout: 42 * time.Minute,
|
IdleTimeout: 42 * time.Minute,
|
||||||
KeepAlive: true,
|
KeepAlive: true,
|
||||||
|
@ -93,7 +93,7 @@ var _ = Describe("Server", func() {
|
||||||
Expect(server.config.Versions).To(Equal(supportedVersions))
|
Expect(server.config.Versions).To(Equal(supportedVersions))
|
||||||
Expect(server.config.HandshakeTimeout).To(Equal(1337 * time.Hour))
|
Expect(server.config.HandshakeTimeout).To(Equal(1337 * time.Hour))
|
||||||
Expect(server.config.IdleTimeout).To(Equal(42 * time.Minute))
|
Expect(server.config.IdleTimeout).To(Equal(42 * time.Minute))
|
||||||
Expect(reflect.ValueOf(server.config.AcceptCookie)).To(Equal(reflect.ValueOf(acceptCookie)))
|
Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(acceptToken)))
|
||||||
Expect(server.config.KeepAlive).To(BeTrue())
|
Expect(server.config.KeepAlive).To(BeTrue())
|
||||||
Expect(server.config.StatelessResetKey).To(Equal([]byte("foobar")))
|
Expect(server.config.StatelessResetKey).To(Equal([]byte("foobar")))
|
||||||
// stop the listener
|
// stop the listener
|
||||||
|
@ -179,19 +179,19 @@ var _ = Describe("Server", func() {
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("decodes the cookie from the Token field", func() {
|
It("decodes the token from the Token field", func() {
|
||||||
raddr := &net.UDPAddr{
|
raddr := &net.UDPAddr{
|
||||||
IP: net.IPv4(192, 168, 13, 37),
|
IP: net.IPv4(192, 168, 13, 37),
|
||||||
Port: 1337,
|
Port: 1337,
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
serv.config.AcceptCookie = func(addr net.Addr, cookie *Cookie) bool {
|
serv.config.AcceptToken = func(addr net.Addr, token *Token) bool {
|
||||||
Expect(addr).To(Equal(raddr))
|
Expect(addr).To(Equal(raddr))
|
||||||
Expect(cookie).ToNot(BeNil())
|
Expect(token).ToNot(BeNil())
|
||||||
close(done)
|
close(done)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
token, err := serv.cookieGenerator.NewToken(raddr, nil)
|
token, err := serv.tokenGenerator.NewToken(raddr, nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
packet := getPacket(&wire.Header{
|
packet := getPacket(&wire.Header{
|
||||||
IsLongHeader: true,
|
IsLongHeader: true,
|
||||||
|
@ -204,15 +204,15 @@ var _ = Describe("Server", func() {
|
||||||
Eventually(done).Should(BeClosed())
|
Eventually(done).Should(BeClosed())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("passes an empty cookie to the callback, if decoding fails", func() {
|
It("passes an empty token to the callback, if decoding fails", func() {
|
||||||
raddr := &net.UDPAddr{
|
raddr := &net.UDPAddr{
|
||||||
IP: net.IPv4(192, 168, 13, 37),
|
IP: net.IPv4(192, 168, 13, 37),
|
||||||
Port: 1337,
|
Port: 1337,
|
||||||
}
|
}
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
serv.config.AcceptCookie = func(addr net.Addr, cookie *Cookie) bool {
|
serv.config.AcceptToken = func(addr net.Addr, token *Token) bool {
|
||||||
Expect(addr).To(Equal(raddr))
|
Expect(addr).To(Equal(raddr))
|
||||||
Expect(cookie).To(BeNil())
|
Expect(token).To(BeNil())
|
||||||
close(done)
|
close(done)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -249,8 +249,8 @@ var _ = Describe("Server", func() {
|
||||||
Expect(hdr.SupportedVersions).ToNot(ContainElement(protocol.VersionNumber(0x42)))
|
Expect(hdr.SupportedVersions).ToNot(ContainElement(protocol.VersionNumber(0x42)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("replies with a Retry packet, if a Cookie is required", func() {
|
It("replies with a Retry packet, if a Token is required", func() {
|
||||||
serv.config.AcceptCookie = func(_ net.Addr, _ *Cookie) bool { return false }
|
serv.config.AcceptToken = func(_ net.Addr, _ *Token) bool { return false }
|
||||||
hdr := &wire.Header{
|
hdr := &wire.Header{
|
||||||
IsLongHeader: true,
|
IsLongHeader: true,
|
||||||
Type: protocol.PacketTypeInitial,
|
Type: protocol.PacketTypeInitial,
|
||||||
|
@ -272,8 +272,8 @@ var _ = Describe("Server", func() {
|
||||||
Expect(replyHdr.Token).ToNot(BeEmpty())
|
Expect(replyHdr.Token).ToNot(BeEmpty())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("creates a session, if no Cookie is required", func() {
|
It("creates a session, if no Token is required", func() {
|
||||||
serv.config.AcceptCookie = func(_ net.Addr, _ *Cookie) bool { return true }
|
serv.config.AcceptToken = func(_ net.Addr, _ *Token) bool { return true }
|
||||||
hdr := &wire.Header{
|
hdr := &wire.Header{
|
||||||
IsLongHeader: true,
|
IsLongHeader: true,
|
||||||
Type: protocol.PacketTypeInitial,
|
Type: protocol.PacketTypeInitial,
|
||||||
|
@ -320,7 +320,7 @@ var _ = Describe("Server", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects new connection attempts if the accept queue is full", func() {
|
It("rejects new connection attempts if the accept queue is full", func() {
|
||||||
serv.config.AcceptCookie = func(_ net.Addr, _ *Cookie) bool { return true }
|
serv.config.AcceptToken = func(_ net.Addr, _ *Token) bool { return true }
|
||||||
senderAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 42}
|
senderAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 42}
|
||||||
|
|
||||||
hdr := &wire.Header{
|
hdr := &wire.Header{
|
||||||
|
@ -375,7 +375,7 @@ var _ = Describe("Server", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("doesn't accept new sessions if they were closed in the mean time", func() {
|
It("doesn't accept new sessions if they were closed in the mean time", func() {
|
||||||
serv.config.AcceptCookie = func(_ net.Addr, _ *Cookie) bool { return true }
|
serv.config.AcceptToken = func(_ net.Addr, _ *Token) bool { return true }
|
||||||
senderAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 42}
|
senderAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 42}
|
||||||
|
|
||||||
hdr := &wire.Header{
|
hdr := &wire.Header{
|
||||||
|
@ -543,51 +543,51 @@ var _ = Describe("Server", func() {
|
||||||
var _ = Describe("default source address verification", func() {
|
var _ = Describe("default source address verification", func() {
|
||||||
It("accepts a token", func() {
|
It("accepts a token", func() {
|
||||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
||||||
cookie := &Cookie{
|
token := &Token{
|
||||||
RemoteAddr: "192.168.0.1",
|
RemoteAddr: "192.168.0.1",
|
||||||
SentTime: time.Now().Add(-protocol.CookieExpiryTime).Add(time.Second), // will expire in 1 second
|
SentTime: time.Now().Add(-protocol.TokenExpiryTime).Add(time.Second), // will expire in 1 second
|
||||||
}
|
}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, cookie)).To(BeTrue())
|
Expect(defaultAcceptToken(remoteAddr, token)).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("requests verification if no token is provided", func() {
|
It("requests verification if no token is provided", func() {
|
||||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, nil)).To(BeFalse())
|
Expect(defaultAcceptToken(remoteAddr, nil)).To(BeFalse())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects a token if the address doesn't match", func() {
|
It("rejects a token if the address doesn't match", func() {
|
||||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
||||||
cookie := &Cookie{
|
token := &Token{
|
||||||
RemoteAddr: "127.0.0.1",
|
RemoteAddr: "127.0.0.1",
|
||||||
SentTime: time.Now(),
|
SentTime: time.Now(),
|
||||||
}
|
}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, cookie)).To(BeFalse())
|
Expect(defaultAcceptToken(remoteAddr, token)).To(BeFalse())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("accepts a token for a remote address is not a UDP address", func() {
|
It("accepts a token for a remote address is not a UDP address", func() {
|
||||||
remoteAddr := &net.TCPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1337}
|
remoteAddr := &net.TCPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1337}
|
||||||
cookie := &Cookie{
|
token := &Token{
|
||||||
RemoteAddr: "192.168.0.1:1337",
|
RemoteAddr: "192.168.0.1:1337",
|
||||||
SentTime: time.Now(),
|
SentTime: time.Now(),
|
||||||
}
|
}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, cookie)).To(BeTrue())
|
Expect(defaultAcceptToken(remoteAddr, token)).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects an invalid token for a remote address is not a UDP address", func() {
|
It("rejects an invalid token for a remote address is not a UDP address", func() {
|
||||||
remoteAddr := &net.TCPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1337}
|
remoteAddr := &net.TCPAddr{IP: net.IPv4(192, 168, 0, 1), Port: 1337}
|
||||||
cookie := &Cookie{
|
token := &Token{
|
||||||
RemoteAddr: "192.168.0.1:7331", // mismatching port
|
RemoteAddr: "192.168.0.1:7331", // mismatching port
|
||||||
SentTime: time.Now(),
|
SentTime: time.Now(),
|
||||||
}
|
}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, cookie)).To(BeFalse())
|
Expect(defaultAcceptToken(remoteAddr, token)).To(BeFalse())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects an expired token", func() {
|
It("rejects an expired token", func() {
|
||||||
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
remoteAddr := &net.UDPAddr{IP: net.IPv4(192, 168, 0, 1)}
|
||||||
cookie := &Cookie{
|
token := &Token{
|
||||||
RemoteAddr: "192.168.0.1",
|
RemoteAddr: "192.168.0.1",
|
||||||
SentTime: time.Now().Add(-protocol.CookieExpiryTime).Add(-time.Second), // expired 1 second ago
|
SentTime: time.Now().Add(-protocol.TokenExpiryTime).Add(-time.Second), // expired 1 second ago
|
||||||
}
|
}
|
||||||
Expect(defaultAcceptCookie(remoteAddr, cookie)).To(BeFalse())
|
Expect(defaultAcceptToken(remoteAddr, token)).To(BeFalse())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue