k8s.io/kubernetes@v1.29.3/test/images/regression-issue-74839/main.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "log" 22 "net" 23 "os" 24 "strings" 25 "time" 26 27 netutils "k8s.io/utils/net" 28 ) 29 30 // TCP port to listen 31 const port = 9000 32 33 func main() { 34 ips := getIPs() 35 if len(ips) == 0 { 36 panic("No valid IP found") 37 } 38 39 // listen TCP packets to inject the out of order TCP packets 40 for _, ip := range ips { 41 log.Printf("external ip: %v", ip.String()) 42 go probe(ip.String()) 43 } 44 45 log.Printf("listen on %v:%d", "0.0.0.0", port) 46 47 // open a server listening to establish the TCP connections 48 listener, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port)) 49 if err != nil { 50 panic(err) 51 } 52 53 for { 54 conn, err := listener.Accept() 55 if err != nil { 56 panic(err) 57 } 58 59 go func(conn net.Conn) { 60 // Close the connection after 10 secs 61 time.Sleep(10 * time.Second) 62 conn.Close() 63 }(conn) 64 } 65 } 66 67 func probe(ip string) { 68 log.Printf("probing %v", ip) 69 70 ipAddr, err := net.ResolveIPAddr("ip:tcp", ip) 71 if err != nil { 72 panic(err) 73 } 74 75 conn, err := net.ListenIP("ip:tcp", ipAddr) 76 if err != nil { 77 panic(err) 78 } 79 80 pending := make(map[string]uint32) 81 82 var buffer [4096]byte 83 for { 84 n, addr, err := conn.ReadFrom(buffer[:]) 85 if err != nil { 86 log.Printf("conn.ReadFrom() error: %v", err) 87 continue 88 } 89 90 pkt := &tcpPacket{} 91 data, err := pkt.decode(buffer[:n]) 92 if err != nil { 93 log.Printf("tcp packet parse error: %v", err) 94 continue 95 } 96 97 if pkt.DestPort != 9000 { 98 continue 99 } 100 101 log.Printf("tcp packet: %+v, flag: %v, data: %v, addr: %v", pkt, pkt.FlagString(), data, addr) 102 103 if pkt.Flags&SYN != 0 { 104 pending[addr.String()] = pkt.Seq + 1 105 continue 106 } 107 if pkt.Flags&RST != 0 { 108 log.Println("ERROR: RST received") 109 } 110 if pkt.Flags&ACK != 0 { 111 if seq, ok := pending[addr.String()]; ok { 112 log.Println("connection established") 113 delete(pending, addr.String()) 114 115 badPkt := &tcpPacket{ 116 SrcPort: pkt.DestPort, 117 DestPort: pkt.SrcPort, 118 Ack: seq, 119 Seq: pkt.Ack - 100000, // Bad: seq out-of-window 120 Flags: (5 << 12) | PSH | ACK, // Offset and Flags oooo000F FFFFFFFF (o:offset, F:flags) 121 WindowSize: pkt.WindowSize, 122 } 123 124 data := []byte("boom!!!") 125 remoteIP := netutils.ParseIPSloppy(addr.String()) 126 localIP := netutils.ParseIPSloppy(conn.LocalAddr().String()) 127 _, err := conn.WriteTo(badPkt.encode(localIP, remoteIP, data[:]), addr) 128 if err != nil { 129 log.Printf("conn.WriteTo() error: %v", err) 130 } else { 131 log.Println("boom packet injected") 132 } 133 } 134 } 135 } 136 } 137 138 // getIPs gets the IPs from the downward API 139 // we don't have to validate the IPs because 140 // they are validated previously by kubernetes/CNI 141 func getIPs() []net.IP { 142 var ips []net.IP 143 podIP, podIPs := os.Getenv("POD_IP"), os.Getenv("POD_IPS") 144 if podIPs != "" { 145 for _, ip := range strings.Split(podIPs, ",") { 146 ips = append(ips, netutils.ParseIPSloppy(ip)) 147 } 148 } else if podIP != "" { 149 ips = append(ips, netutils.ParseIPSloppy(podIP)) 150 } 151 return ips 152 }