748 lines
19 KiB
Go
748 lines
19 KiB
Go
|
|
package bcap
|
||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/gopacket/gopacket"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestObserveTCPStateTransitions(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000000, 0)
|
||
|
|
|
||
|
|
cases := []struct {
|
||
|
|
name string
|
||
|
|
packet func(time.Time) observedPacket
|
||
|
|
want uint8
|
||
|
|
wantLen int
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "syn",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 100,
|
||
|
|
syn: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpConnect1,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "synack",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.2",
|
||
|
|
dstIP: "10.0.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40000,
|
||
|
|
seq: 500,
|
||
|
|
ack: 101,
|
||
|
|
syn: true,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpConnect2,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "ack",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpConnect3,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "server-ack",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.2",
|
||
|
|
dstIP: "10.0.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40000,
|
||
|
|
seq: 501,
|
||
|
|
ack: 101,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpAckOk,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "client-data",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("hello"),
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpAckOk,
|
||
|
|
wantLen: 5,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "retransmission",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("hello"),
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpRetransmit,
|
||
|
|
wantLen: 5,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "server-ack-after-data",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.2",
|
||
|
|
dstIP: "10.0.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40000,
|
||
|
|
seq: 501,
|
||
|
|
ack: 106,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpAckOk,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "keepalive",
|
||
|
|
packet: func(ts time.Time) observedPacket {
|
||
|
|
return mustObservePacket(t, analyzer, mustBuildTCPPacket(t, ts, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 105,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: StateTcpKeepalive,
|
||
|
|
wantLen: 0,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for i, tc := range cases {
|
||
|
|
info := tc.packet(base.Add(time.Duration(i) * time.Millisecond))
|
||
|
|
if info.StateDescript() != tc.want {
|
||
|
|
t.Fatalf("%s: state = %d, want %d", tc.name, info.StateDescript(), tc.want)
|
||
|
|
}
|
||
|
|
if info.TcpPayloads() != tc.wantLen {
|
||
|
|
t.Fatalf("%s: payload len = %d, want %d", tc.name, info.TcpPayloads(), tc.wantLen)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPRepeatedKeepaliveWithoutReverseResponse(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000500, 0)
|
||
|
|
|
||
|
|
first := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
if first.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("first probe state = %d, want %d", first.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
|
||
|
|
second := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(75*time.Second), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
if second.StateDescript() != StateTcpKeepalive {
|
||
|
|
t.Fatalf("second probe state = %d, want %d", second.StateDescript(), StateTcpKeepalive)
|
||
|
|
}
|
||
|
|
|
||
|
|
third := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(150*time.Second), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
if third.StateDescript() != StateTcpKeepalive {
|
||
|
|
t.Fatalf("third probe state = %d, want %d", third.StateDescript(), StateTcpKeepalive)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPKeepaliveResponseAck(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000530, 0)
|
||
|
|
|
||
|
|
_ = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
|
||
|
|
probe := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(75*time.Second), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
if probe.StateDescript() != StateTcpKeepalive {
|
||
|
|
t.Fatalf("probe state = %d, want %d", probe.StateDescript(), StateTcpKeepalive)
|
||
|
|
}
|
||
|
|
|
||
|
|
resp := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(75*time.Second+50*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.110.99",
|
||
|
|
dstIP: "122.210.105.240",
|
||
|
|
srcPort: 60818,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 2951532891,
|
||
|
|
ack: 172126746,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 1024,
|
||
|
|
}))
|
||
|
|
if resp.StateDescript() != StateTcpKeepalive {
|
||
|
|
t.Fatalf("keepalive response state = %d, want %d", resp.StateDescript(), StateTcpKeepalive)
|
||
|
|
}
|
||
|
|
if resp.Hints.TCP == nil || resp.Hints.TCP.Event != TCPEventKeepaliveResp {
|
||
|
|
t.Fatalf("response event = %#v, want %q", resp.Hints.TCP, TCPEventKeepaliveResp)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPKeepaliveResponseAfterWindowFallsBackToAck(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000540, 0)
|
||
|
|
|
||
|
|
_ = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
|
||
|
|
probe := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(75*time.Second), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.105.240",
|
||
|
|
dstIP: "122.210.110.99",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 172126745,
|
||
|
|
ack: 2951532891,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 258,
|
||
|
|
}))
|
||
|
|
if probe.StateDescript() != StateTcpKeepalive {
|
||
|
|
t.Fatalf("probe state = %d, want %d", probe.StateDescript(), StateTcpKeepalive)
|
||
|
|
}
|
||
|
|
|
||
|
|
resp := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(75*time.Second+keepaliveResponseMaxDelay+time.Second), tcpPacketSpec{
|
||
|
|
srcIP: "122.210.110.99",
|
||
|
|
dstIP: "122.210.105.240",
|
||
|
|
srcPort: 60818,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 2951532891,
|
||
|
|
ack: 172126746,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 1024,
|
||
|
|
}))
|
||
|
|
if resp.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("late keepalive response state = %d, want %d", resp.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPRepeatedAckWithoutGapStaysAck(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000550, 0)
|
||
|
|
|
||
|
|
_ = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "10.10.0.1",
|
||
|
|
dstIP: "10.10.0.2",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 5000,
|
||
|
|
ack: 9000,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 512,
|
||
|
|
}))
|
||
|
|
|
||
|
|
next := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(100*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.10.0.1",
|
||
|
|
dstIP: "10.10.0.2",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 60818,
|
||
|
|
seq: 5000,
|
||
|
|
ack: 9000,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 512,
|
||
|
|
}))
|
||
|
|
if next.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("short-gap ack state = %d, want %d", next.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPPostHandshakeDataIsNotConnect3Again(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000565, 0)
|
||
|
|
|
||
|
|
syn := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "10.11.0.1",
|
||
|
|
dstIP: "10.11.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 100,
|
||
|
|
syn: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if syn.StateDescript() != StateTcpConnect1 {
|
||
|
|
t.Fatalf("syn state = %d, want %d", syn.StateDescript(), StateTcpConnect1)
|
||
|
|
}
|
||
|
|
|
||
|
|
synack := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.11.0.2",
|
||
|
|
dstIP: "10.11.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40000,
|
||
|
|
seq: 500,
|
||
|
|
ack: 101,
|
||
|
|
syn: true,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if synack.StateDescript() != StateTcpConnect2 {
|
||
|
|
t.Fatalf("synack state = %d, want %d", synack.StateDescript(), StateTcpConnect2)
|
||
|
|
}
|
||
|
|
|
||
|
|
ack := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(2*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.11.0.1",
|
||
|
|
dstIP: "10.11.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if ack.StateDescript() != StateTcpConnect3 {
|
||
|
|
t.Fatalf("handshake ack state = %d, want %d", ack.StateDescript(), StateTcpConnect3)
|
||
|
|
}
|
||
|
|
|
||
|
|
data := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.11.0.1",
|
||
|
|
dstIP: "10.11.0.2",
|
||
|
|
srcPort: 40000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("hello"),
|
||
|
|
}))
|
||
|
|
if data.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("post-handshake data state = %d, want %d", data.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPHandshakeAcrossSequenceWraparound(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000575, 0)
|
||
|
|
|
||
|
|
syn := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "10.12.0.1",
|
||
|
|
dstIP: "10.12.0.2",
|
||
|
|
srcPort: 40001,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: ^uint32(0),
|
||
|
|
syn: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if syn.StateDescript() != StateTcpConnect1 {
|
||
|
|
t.Fatalf("wrap syn state = %d, want %d", syn.StateDescript(), StateTcpConnect1)
|
||
|
|
}
|
||
|
|
|
||
|
|
synack := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.12.0.2",
|
||
|
|
dstIP: "10.12.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40001,
|
||
|
|
seq: 500,
|
||
|
|
ack: 0,
|
||
|
|
syn: true,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if synack.StateDescript() != StateTcpConnect2 {
|
||
|
|
t.Fatalf("wrap synack state = %d, want %d", synack.StateDescript(), StateTcpConnect2)
|
||
|
|
}
|
||
|
|
|
||
|
|
ack := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(2*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.12.0.1",
|
||
|
|
dstIP: "10.12.0.2",
|
||
|
|
srcPort: 40001,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 0,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if ack.StateDescript() != StateTcpConnect3 {
|
||
|
|
t.Fatalf("wrap handshake ack state = %d, want %d", ack.StateDescript(), StateTcpConnect3)
|
||
|
|
}
|
||
|
|
|
||
|
|
data := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.12.0.1",
|
||
|
|
dstIP: "10.12.0.2",
|
||
|
|
srcPort: 40001,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 0,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("hi"),
|
||
|
|
}))
|
||
|
|
if data.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("wrap post-handshake data state = %d, want %d", data.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPGapFillDoesNotLookLikeRetransmission(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700000580, 0)
|
||
|
|
|
||
|
|
_, _ = mustEstablishTCPConnection(
|
||
|
|
t,
|
||
|
|
analyzer,
|
||
|
|
base,
|
||
|
|
"10.20.0.1",
|
||
|
|
44000,
|
||
|
|
"10.20.0.2",
|
||
|
|
3306,
|
||
|
|
100,
|
||
|
|
500,
|
||
|
|
)
|
||
|
|
|
||
|
|
_ = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.20.0.2",
|
||
|
|
dstIP: "10.20.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 44000,
|
||
|
|
seq: 501,
|
||
|
|
ack: 101,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
|
||
|
|
first := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(4*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.20.0.1",
|
||
|
|
dstIP: "10.20.0.2",
|
||
|
|
srcPort: 44000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("AAAAA"),
|
||
|
|
}))
|
||
|
|
if first.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("first payload state = %d, want %d", first.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
|
||
|
|
later := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(5*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.20.0.1",
|
||
|
|
dstIP: "10.20.0.2",
|
||
|
|
srcPort: 44000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 111,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("CCCCC"),
|
||
|
|
}))
|
||
|
|
if later.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("later payload state = %d, want %d", later.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
|
||
|
|
gapFill := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(6*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.20.0.1",
|
||
|
|
dstIP: "10.20.0.2",
|
||
|
|
srcPort: 44000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 106,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
payload: []byte("BBBBB"),
|
||
|
|
}))
|
||
|
|
if gapFill.StateDescript() != StateTcpAckOk {
|
||
|
|
t.Fatalf("gap-fill state = %d, want %d", gapFill.StateDescript(), StateTcpAckOk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPRSTClearsTrackedFlows(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700001000, 0)
|
||
|
|
|
||
|
|
inputs := []gopacket.Packet{
|
||
|
|
mustBuildTCPPacket(t, base, tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40001,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 100,
|
||
|
|
syn: true,
|
||
|
|
window: 4096,
|
||
|
|
}),
|
||
|
|
mustBuildTCPPacket(t, base.Add(time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.2",
|
||
|
|
dstIP: "10.0.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40001,
|
||
|
|
seq: 500,
|
||
|
|
ack: 101,
|
||
|
|
syn: true,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}),
|
||
|
|
mustBuildTCPPacket(t, base.Add(2*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.1",
|
||
|
|
dstIP: "10.0.0.2",
|
||
|
|
srcPort: 40001,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}),
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, packet := range inputs {
|
||
|
|
_ = mustObservePacket(t, analyzer, packet)
|
||
|
|
}
|
||
|
|
|
||
|
|
info := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.0.2",
|
||
|
|
dstIP: "10.0.0.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 40001,
|
||
|
|
seq: 501,
|
||
|
|
ack: 101,
|
||
|
|
ackFlag: true,
|
||
|
|
rst: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpRst {
|
||
|
|
t.Fatalf("rst state = %d, want %d", info.StateDescript(), StateTcpRst)
|
||
|
|
}
|
||
|
|
if got := analyzer.Tracker().ActiveFlowCount(); got != 0 {
|
||
|
|
t.Fatalf("active flow count = %d, want 0", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPFourWayCloseSequence(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700004000, 0)
|
||
|
|
|
||
|
|
_, _ = mustEstablishTCPConnection(
|
||
|
|
t,
|
||
|
|
analyzer,
|
||
|
|
base,
|
||
|
|
"10.0.1.1",
|
||
|
|
41000,
|
||
|
|
"10.0.1.2",
|
||
|
|
3306,
|
||
|
|
100,
|
||
|
|
500,
|
||
|
|
)
|
||
|
|
|
||
|
|
info := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.1.1",
|
||
|
|
dstIP: "10.0.1.2",
|
||
|
|
srcPort: 41000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
fin: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect1 {
|
||
|
|
t.Fatalf("client fin state = %d, want %d", info.StateDescript(), StateTcpDisconnect1)
|
||
|
|
}
|
||
|
|
|
||
|
|
info = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(4*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.1.2",
|
||
|
|
dstIP: "10.0.1.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 41000,
|
||
|
|
seq: 501,
|
||
|
|
ack: 102,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect2 {
|
||
|
|
t.Fatalf("server ack state = %d, want %d", info.StateDescript(), StateTcpDisconnect2)
|
||
|
|
}
|
||
|
|
|
||
|
|
info = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(5*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.1.2",
|
||
|
|
dstIP: "10.0.1.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 41000,
|
||
|
|
seq: 501,
|
||
|
|
ack: 102,
|
||
|
|
ackFlag: true,
|
||
|
|
fin: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect3 {
|
||
|
|
t.Fatalf("server fin state = %d, want %d", info.StateDescript(), StateTcpDisconnect3)
|
||
|
|
}
|
||
|
|
|
||
|
|
info = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(6*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.1.1",
|
||
|
|
dstIP: "10.0.1.2",
|
||
|
|
srcPort: 41000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 102,
|
||
|
|
ack: 502,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect4 {
|
||
|
|
t.Fatalf("final ack state = %d, want %d", info.StateDescript(), StateTcpDisconnect4)
|
||
|
|
}
|
||
|
|
if got := analyzer.Tracker().ActiveFlowCount(); got != 0 {
|
||
|
|
t.Fatalf("active flow count after close = %d, want 0", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestObserveTCPDisconnect23CombinedFinAck(t *testing.T) {
|
||
|
|
analyzer := newTestAnalyzer()
|
||
|
|
defer analyzer.Stop()
|
||
|
|
base := time.Unix(1700005000, 0)
|
||
|
|
|
||
|
|
_, _ = mustEstablishTCPConnection(
|
||
|
|
t,
|
||
|
|
analyzer,
|
||
|
|
base,
|
||
|
|
"10.0.2.1",
|
||
|
|
42000,
|
||
|
|
"10.0.2.2",
|
||
|
|
3306,
|
||
|
|
100,
|
||
|
|
500,
|
||
|
|
)
|
||
|
|
|
||
|
|
info := mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(3*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.2.1",
|
||
|
|
dstIP: "10.0.2.2",
|
||
|
|
srcPort: 42000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 101,
|
||
|
|
ack: 501,
|
||
|
|
ackFlag: true,
|
||
|
|
fin: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect1 {
|
||
|
|
t.Fatalf("client fin state = %d, want %d", info.StateDescript(), StateTcpDisconnect1)
|
||
|
|
}
|
||
|
|
|
||
|
|
info = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(4*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.2.2",
|
||
|
|
dstIP: "10.0.2.1",
|
||
|
|
srcPort: 3306,
|
||
|
|
dstPort: 42000,
|
||
|
|
seq: 600,
|
||
|
|
ack: 102,
|
||
|
|
ackFlag: true,
|
||
|
|
fin: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect23 {
|
||
|
|
t.Fatalf("combined fin-ack state = %d, want %d", info.StateDescript(), StateTcpDisconnect23)
|
||
|
|
}
|
||
|
|
|
||
|
|
info = mustObservePacket(t, analyzer, mustBuildTCPPacket(t, base.Add(5*time.Millisecond), tcpPacketSpec{
|
||
|
|
srcIP: "10.0.2.1",
|
||
|
|
dstIP: "10.0.2.2",
|
||
|
|
srcPort: 42000,
|
||
|
|
dstPort: 3306,
|
||
|
|
seq: 102,
|
||
|
|
ack: 601,
|
||
|
|
ackFlag: true,
|
||
|
|
window: 4096,
|
||
|
|
}))
|
||
|
|
if info.StateDescript() != StateTcpDisconnect4 {
|
||
|
|
t.Fatalf("final ack state = %d, want %d", info.StateDescript(), StateTcpDisconnect4)
|
||
|
|
}
|
||
|
|
if got := analyzer.Tracker().ActiveFlowCount(); got != 0 {
|
||
|
|
t.Fatalf("active flow count after combined close = %d, want 0", got)
|
||
|
|
}
|
||
|
|
}
|