forked from quic-go/quic-go
improve the MITM tests
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
|||||||
quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy"
|
quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy"
|
||||||
"github.com/lucas-clemente/quic-go/integrationtests/tools/testserver"
|
"github.com/lucas-clemente/quic-go/integrationtests/tools/testserver"
|
||||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||||
|
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||||
"github.com/lucas-clemente/quic-go/internal/testutils"
|
"github.com/lucas-clemente/quic-go/internal/testutils"
|
||||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@@ -288,8 +289,6 @@ var _ = Describe("MITM test", func() {
|
|||||||
// from serverConn to client's remoteAddr
|
// from serverConn to client's remoteAddr
|
||||||
// expects hdr from an Initial packet intercepted from client
|
// expects hdr from an Initial packet intercepted from client
|
||||||
sendForgedVersionNegotationPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
sendForgedVersionNegotationPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
// Create fake version negotiation packet with no supported versions
|
// Create fake version negotiation packet with no supported versions
|
||||||
versions := []protocol.VersionNumber{}
|
versions := []protocol.VersionNumber{}
|
||||||
packet, _ := wire.ComposeVersionNegotiation(hdr.SrcConnectionID, hdr.DestConnectionID, versions)
|
packet, _ := wire.ComposeVersionNegotiation(hdr.SrcConnectionID, hdr.DestConnectionID, versions)
|
||||||
@@ -303,8 +302,6 @@ var _ = Describe("MITM test", func() {
|
|||||||
// from serverConn to client's remoteAddr
|
// from serverConn to client's remoteAddr
|
||||||
// expects hdr from an Initial packet intercepted from client
|
// expects hdr from an Initial packet intercepted from client
|
||||||
sendForgedRetryPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
sendForgedRetryPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
var x byte = 0x12
|
var x byte = 0x12
|
||||||
fakeSrcConnID := protocol.ConnectionID{x, x, x, x, x, x, x, x}
|
fakeSrcConnID := protocol.ConnectionID{x, x, x, x, x, x, x, x}
|
||||||
retryPacket := testutils.ComposeRetryPacket(fakeSrcConnID, hdr.SrcConnectionID, hdr.DestConnectionID, []byte("token"), hdr.Version)
|
retryPacket := testutils.ComposeRetryPacket(fakeSrcConnID, hdr.SrcConnectionID, hdr.DestConnectionID, []byte("token"), hdr.Version)
|
||||||
@@ -316,8 +313,6 @@ var _ = Describe("MITM test", func() {
|
|||||||
// Send a forged Initial packet with no frames to client
|
// Send a forged Initial packet with no frames to client
|
||||||
// expects hdr from an Initial packet intercepted from client
|
// expects hdr from an Initial packet intercepted from client
|
||||||
sendForgedInitialPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
sendForgedInitialPacket := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
initialPacket := testutils.ComposeInitialPacket(hdr.DestConnectionID, hdr.SrcConnectionID, hdr.Version, hdr.DestConnectionID, nil)
|
initialPacket := testutils.ComposeInitialPacket(hdr.DestConnectionID, hdr.SrcConnectionID, hdr.Version, hdr.DestConnectionID, nil)
|
||||||
_, err := conn.WriteTo(initialPacket, remoteAddr)
|
_, err := conn.WriteTo(initialPacket, remoteAddr)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@@ -326,8 +321,6 @@ var _ = Describe("MITM test", func() {
|
|||||||
// Send a forged Initial packet with ACK for random packet to client
|
// Send a forged Initial packet with ACK for random packet to client
|
||||||
// expects hdr from an Initial packet intercepted from client
|
// expects hdr from an Initial packet intercepted from client
|
||||||
sendForgedInitialPacketWithAck := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
sendForgedInitialPacketWithAck := func(conn net.PacketConn, remoteAddr net.Addr, hdr *wire.Header) {
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
// Fake Initial with ACK for packet 2 (unsent)
|
// Fake Initial with ACK for packet 2 (unsent)
|
||||||
ackFrame := testutils.ComposeAckFrame(2, 2)
|
ackFrame := testutils.ComposeAckFrame(2, 2)
|
||||||
initialPacket := testutils.ComposeInitialPacket(hdr.DestConnectionID, hdr.SrcConnectionID, hdr.Version, hdr.DestConnectionID, []wire.Frame{ackFrame})
|
initialPacket := testutils.ComposeInitialPacket(hdr.DestConnectionID, hdr.SrcConnectionID, hdr.Version, hdr.DestConnectionID, []wire.Frame{ackFrame})
|
||||||
@@ -335,9 +328,7 @@ var _ = Describe("MITM test", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
// runTestFail succeeds if an error occurs in dialing
|
runTest := func(delayCb quicproxy.DelayCallback) error {
|
||||||
// expects a proxy delay function that runs every time a packet is received
|
|
||||||
runTestFail := func(delayCb quicproxy.DelayCallback) {
|
|
||||||
startServerAndProxy(delayCb, nil)
|
startServerAndProxy(delayCb, nil)
|
||||||
raddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", proxy.LocalPort()))
|
raddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", proxy.LocalPort()))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@@ -349,15 +340,15 @@ var _ = Describe("MITM test", func() {
|
|||||||
&quic.Config{
|
&quic.Config{
|
||||||
Versions: []protocol.VersionNumber{version},
|
Versions: []protocol.VersionNumber{version},
|
||||||
ConnectionIDLength: connIDLen,
|
ConnectionIDLength: connIDLen,
|
||||||
|
HandshakeTimeout: 2 * time.Second,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
Expect(err).To(HaveOccurred())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// fails immediately because client connection closes when it can't find compatible version
|
// fails immediately because client connection closes when it can't find compatible version
|
||||||
It("fails when a forged version negotiation packet is sent to client", func() {
|
It("fails when a forged version negotiation packet is sent to client", func() {
|
||||||
delayCb := func(dir quicproxy.Direction, raw []byte) time.Duration {
|
delayCb := func(dir quicproxy.Direction, raw []byte) time.Duration {
|
||||||
fmt.Println()
|
|
||||||
if dir == quicproxy.DirectionIncoming {
|
if dir == quicproxy.DirectionIncoming {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
|
|
||||||
@@ -368,18 +359,20 @@ var _ = Describe("MITM test", func() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
go sendForgedVersionNegotationPacket(serverConn, clientConn.LocalAddr(), hdr)
|
sendForgedVersionNegotationPacket(serverConn, clientConn.LocalAddr(), hdr)
|
||||||
}
|
}
|
||||||
return rtt / 2
|
return rtt / 2
|
||||||
}
|
}
|
||||||
runTestFail(delayCb)
|
err := runTest(delayCb)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.Error()).To(ContainSubstring("No compatible QUIC version found."))
|
||||||
})
|
})
|
||||||
|
|
||||||
// times out, because client doesn't accept subsequent real retry packets from server
|
// times out, because client doesn't accept subsequent real retry packets from server
|
||||||
// as it has already accepted a retry.
|
// as it has already accepted a retry.
|
||||||
// TODO: determine behavior when server does not send Retry packets
|
// TODO: determine behavior when server does not send Retry packets
|
||||||
initialPacketIntercepted := false
|
It("fails when a forged Retry packet with modified srcConnID is sent to client", func() {
|
||||||
It("fails when a forged retry packet with modified srcConnID is sent to client", func() {
|
var initialPacketIntercepted bool
|
||||||
delayCb := func(dir quicproxy.Direction, raw []byte) time.Duration {
|
delayCb := func(dir quicproxy.Direction, raw []byte) time.Duration {
|
||||||
if dir == quicproxy.DirectionIncoming && !initialPacketIntercepted {
|
if dir == quicproxy.DirectionIncoming && !initialPacketIntercepted {
|
||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
@@ -392,11 +385,13 @@ var _ = Describe("MITM test", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialPacketIntercepted = true
|
initialPacketIntercepted = true
|
||||||
go sendForgedRetryPacket(serverConn, clientConn.LocalAddr(), hdr)
|
sendForgedRetryPacket(serverConn, clientConn.LocalAddr(), hdr)
|
||||||
}
|
}
|
||||||
return rtt / 2
|
return rtt / 2
|
||||||
}
|
}
|
||||||
runTestFail(delayCb)
|
err := runTest(delayCb)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
// times out, because client doesn't accept real retry packets from server because
|
// times out, because client doesn't accept real retry packets from server because
|
||||||
@@ -414,11 +409,13 @@ var _ = Describe("MITM test", func() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
go sendForgedInitialPacket(serverConn, clientConn.LocalAddr(), hdr)
|
sendForgedInitialPacket(serverConn, clientConn.LocalAddr(), hdr)
|
||||||
}
|
}
|
||||||
return rtt
|
return rtt
|
||||||
}
|
}
|
||||||
runTestFail(delayCb)
|
err := runTest(delayCb)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
// client connection closes immediately on receiving ack for unsent packet
|
// client connection closes immediately on receiving ack for unsent packet
|
||||||
@@ -434,11 +431,15 @@ var _ = Describe("MITM test", func() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
go sendForgedInitialPacketWithAck(serverConn, clientConn.LocalAddr(), hdr)
|
sendForgedInitialPacketWithAck(serverConn, clientConn.LocalAddr(), hdr)
|
||||||
}
|
}
|
||||||
return rtt
|
return rtt
|
||||||
}
|
}
|
||||||
runTestFail(delayCb)
|
err := runTest(delayCb)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err).To(BeAssignableToTypeOf(&qerr.QuicError{}))
|
||||||
|
Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.ProtocolViolation))
|
||||||
|
Expect(err.Error()).To(ContainSubstring("Received ACK for an unsent packet"))
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user