mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #95328 from aojea/conntrack_invalid
add ipv6 support to the image issue-74839
This commit is contained in:
commit
82cc713b13
@ -1,4 +1,4 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
@ -29,3 +29,9 @@ filegroup(
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["tcp_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
@ -1,2 +1,3 @@
|
||||
approvers:
|
||||
- anfernee
|
||||
- aojea
|
||||
|
@ -1 +1 @@
|
||||
1.1
|
||||
1.2
|
||||
|
@ -17,20 +17,33 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TCP port to listen
|
||||
const port = 9000
|
||||
|
||||
func main() {
|
||||
ip := getIP().String()
|
||||
log.Printf("external ip: %v", ip)
|
||||
ips := getIPs()
|
||||
if len(ips) == 0 {
|
||||
panic("No valid IP found")
|
||||
}
|
||||
|
||||
go probe(ip)
|
||||
// listen TCP packets to inject the out of order TCP packets
|
||||
for _, ip := range ips {
|
||||
log.Printf("external ip: %v", ip.String())
|
||||
go probe(ip.String())
|
||||
}
|
||||
|
||||
log.Printf("listen on %v:9000", "0.0.0.0")
|
||||
log.Printf("listen on %v:%d", "0.0.0.0", port)
|
||||
|
||||
listener, err := net.Listen("tcp", "0.0.0.0:9000")
|
||||
// open a server listening to establish the TCP connections
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -42,6 +55,7 @@ func main() {
|
||||
}
|
||||
|
||||
go func(conn net.Conn) {
|
||||
// Close the connection after 10 secs
|
||||
time.Sleep(10 * time.Second)
|
||||
conn.Close()
|
||||
}(conn)
|
||||
@ -51,12 +65,12 @@ func main() {
|
||||
func probe(ip string) {
|
||||
log.Printf("probing %v", ip)
|
||||
|
||||
ipAddr, err := net.ResolveIPAddr("ip4:tcp", ip)
|
||||
ipAddr, err := net.ResolveIPAddr("ip:tcp", ip)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
conn, err := net.ListenIP("ip4:tcp", ipAddr)
|
||||
conn, err := net.ListenIP("ip:tcp", ipAddr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -89,7 +103,7 @@ func probe(ip string) {
|
||||
continue
|
||||
}
|
||||
if pkt.Flags&RST != 0 {
|
||||
panic("RST received")
|
||||
log.Println("ERROR: RST received")
|
||||
}
|
||||
if pkt.Flags&ACK != 0 {
|
||||
if seq, ok := pending[addr.String()]; ok {
|
||||
@ -111,20 +125,26 @@ func probe(ip string) {
|
||||
_, err := conn.WriteTo(badPkt.encode(localIP, remoteIP, data[:]), addr)
|
||||
if err != nil {
|
||||
log.Printf("conn.WriteTo() error: %v", err)
|
||||
} else {
|
||||
log.Println("boom packet injected")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getIP() net.IP {
|
||||
conn, err := net.Dial("udp", "8.8.8.8:53")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
// getIPs gets the IPs from the downward API
|
||||
// we don't have to validate the IPs because
|
||||
// they are validated previously by kubernetes/CNI
|
||||
func getIPs() []net.IP {
|
||||
var ips []net.IP
|
||||
podIP, podIPs := os.Getenv("POD_IP"), os.Getenv("POD_IPS")
|
||||
if podIPs != "" {
|
||||
for _, ip := range strings.Split(podIPs, ",") {
|
||||
ips = append(ips, net.ParseIP(ip))
|
||||
}
|
||||
} else if podIP != "" {
|
||||
ips = append(ips, net.ParseIP(podIP))
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
|
||||
return localAddr.IP
|
||||
return ips
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
// Control Bits. 6 bits.
|
||||
// 00 01 02 03 04 05
|
||||
// U A P R S F
|
||||
|
||||
// FIN is a TCP flag
|
||||
FIN uint16 = 1 << iota
|
||||
// SYN is a TCP flag
|
||||
@ -52,11 +56,16 @@ const (
|
||||
)
|
||||
|
||||
type tcpPacket struct {
|
||||
SrcPort uint16 // 0
|
||||
DestPort uint16 // 2
|
||||
Seq uint32 // 4
|
||||
Ack uint32 // 8
|
||||
Flags uint16 // 13
|
||||
SrcPort uint16 // 0
|
||||
DestPort uint16 // 2
|
||||
Seq uint32 // 4
|
||||
Ack uint32 // 8
|
||||
// Flags bytes includes
|
||||
// Data Offset. 4 bits.
|
||||
// reserved. 3 bits. (must be zero)
|
||||
// ECN, Explicit Congestion Notification. 3 bits.
|
||||
// Control Bits (Real flags). 6 bits.
|
||||
Flags uint16 // 12
|
||||
WindowSize uint16 // 14
|
||||
Checksum uint16 // 16
|
||||
UrgentPtr uint16 // 18
|
||||
@ -133,16 +142,29 @@ func (t *tcpPacket) encode(src, dest net.IP, data []byte) []byte {
|
||||
|
||||
func checksumTCP(src, dest net.IP, tcpHeader, data []byte) uint16 {
|
||||
log.Printf("calling checksumTCP: %v %v %v %v", src, dest, tcpHeader, data)
|
||||
chk := &tcpChecksumer{}
|
||||
chk := &tcpChecksummer{}
|
||||
|
||||
// Encode pseudoheader.
|
||||
chk.add(src.To4())
|
||||
chk.add(dest.To4())
|
||||
if src.To4() != nil {
|
||||
// IPv4 [ src (4) | dst (4) | rsv (1) | proto (1) | tcp length (2) ] ... | tcp header | data
|
||||
chk.add(src.To4())
|
||||
chk.add(dest.To4())
|
||||
pseudoHeader := make([]byte, 4)
|
||||
pseudoHeader[1] = tcpProtoNum
|
||||
binary.BigEndian.PutUint16(pseudoHeader[2:], uint16(len(data)+len(tcpHeader)))
|
||||
chk.add(pseudoHeader)
|
||||
|
||||
} else {
|
||||
// https://tools.ietf.org/html/rfc2460 IPv6
|
||||
// IPv6 [ src (16) | dst (16) | payload length (4) | Zero (3) | NH/proto (1) ] ... | tcp header | data
|
||||
chk.add(src.To16())
|
||||
chk.add(dest.To16())
|
||||
pseudoHeader := make([]byte, 8)
|
||||
binary.BigEndian.PutUint32(pseudoHeader, uint32(len(data)+len(tcpHeader)))
|
||||
pseudoHeader[7] = tcpProtoNum
|
||||
chk.add(pseudoHeader)
|
||||
}
|
||||
|
||||
var pseudoHeader [4]byte
|
||||
pseudoHeader[1] = tcpProtoNum
|
||||
binary.BigEndian.PutUint16(pseudoHeader[2:], uint16(len(data)+len(tcpHeader)))
|
||||
chk.add(pseudoHeader[:])
|
||||
chk.add(tcpHeader)
|
||||
chk.add(data)
|
||||
|
||||
@ -151,13 +173,13 @@ func checksumTCP(src, dest net.IP, tcpHeader, data []byte) uint16 {
|
||||
return chk.finalize()
|
||||
}
|
||||
|
||||
type tcpChecksumer struct {
|
||||
type tcpChecksummer struct {
|
||||
sum uint32
|
||||
oddByte byte
|
||||
length int
|
||||
}
|
||||
|
||||
func (c *tcpChecksumer) finalize() uint16 {
|
||||
func (c *tcpChecksummer) finalize() uint16 {
|
||||
ret := c.sum
|
||||
if c.length%2 > 0 {
|
||||
ret += uint32(c.oddByte)
|
||||
@ -171,7 +193,7 @@ func (c *tcpChecksumer) finalize() uint16 {
|
||||
return ^uint16(ret)
|
||||
}
|
||||
|
||||
func (c *tcpChecksumer) add(data []byte) {
|
||||
func (c *tcpChecksummer) add(data []byte) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
|
91
test/images/regression-issue-74839/tcp_test.go
Normal file
91
test/images/regression-issue-74839/tcp_test.go
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Partially copied from https://github.com/bowei/lighthouse/blob/master/pkg/probe/tcp_test.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTCPChecksummer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
data [][]byte
|
||||
want uint16
|
||||
}{
|
||||
{
|
||||
desc: "empty",
|
||||
data: [][]byte{},
|
||||
want: 0xffff,
|
||||
},
|
||||
{
|
||||
desc: "1 byte",
|
||||
data: [][]byte{{0x55}},
|
||||
want: 0xffaa,
|
||||
},
|
||||
{
|
||||
desc: "2 bytes",
|
||||
data: [][]byte{{0x55, 0x88}},
|
||||
want: 0x77aa,
|
||||
},
|
||||
{
|
||||
desc: "3 bytes",
|
||||
data: [][]byte{{0x55, 0x88, 0x99}},
|
||||
want: 0x7711,
|
||||
},
|
||||
{
|
||||
desc: "3 bytes / 1 at a time",
|
||||
data: [][]byte{{0x55}, {0x88}, {0x99}},
|
||||
want: 0x7711,
|
||||
},
|
||||
{
|
||||
desc: "3 bytes / 2 1",
|
||||
data: [][]byte{{0x55, 0x88}, {0x99}},
|
||||
want: 0x7711,
|
||||
},
|
||||
{
|
||||
desc: "simple packet",
|
||||
data: [][]byte{
|
||||
{
|
||||
0x7f, 0x00, 0x00, 0x01, // 127.0.0.1
|
||||
0x7f, 0x00, 0x00, 0x01, // 127.0.0.1
|
||||
0x00, 0x06, // TCP proto 6
|
||||
0x00, 0x14, // Size = 20 bytes
|
||||
0x00, 0x50, 0x1f, 0x90, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x50, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
},
|
||||
want: 0xff91,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
c := &tcpChecksummer{}
|
||||
for _, b := range tc.data {
|
||||
c.add(b)
|
||||
}
|
||||
got := c.finalize()
|
||||
if got != tc.want {
|
||||
t.Errorf("c.finalize() = %x, want %x; bytes: %v", got, tc.want, tc.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user