
conntrack does not have any way to track UDP connections, so it relies on timers to delete a connection. The problem is that UDP is connectionless, so a client will keep sending traffic despite the server has gone, thus renewing the conntrack entries. Pods that use portmaps to expose UDP services need to flush the existing conntrack entries on the port exposed when they are created, otherwise conntrack will keep sending the traffic to the previous IP until the connection age (the client stops sending traffic) Signed-off-by: Antonio Ojea <aojea@redhat.com>
87 lines
1.7 KiB
Go
87 lines
1.7 KiB
Go
// Echosvr is a simple TCP echo server
|
|
//
|
|
// It prints its listen address on stdout
|
|
// 127.0.0.1:xxxxx
|
|
// A test should wait for this line, parse it
|
|
// and may then attempt to connect.
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
// Start TCP server
|
|
listener, err := net.Listen("tcp", ":")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer listener.Close()
|
|
// use the same port for UDP
|
|
_, port, err := net.SplitHostPort(listener.Addr().String())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Printf("127.0.0.1:%s\n", port)
|
|
go func() {
|
|
for {
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
go handleConnection(conn)
|
|
}
|
|
}()
|
|
|
|
// Start UDP server
|
|
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%s", port))
|
|
if err != nil {
|
|
log.Fatalf("Error from net.ResolveUDPAddr(): %s", err)
|
|
}
|
|
sock, err := net.ListenUDP("udp", addr)
|
|
if err != nil {
|
|
log.Fatalf("Error from ListenUDP(): %s", err)
|
|
}
|
|
defer sock.Close()
|
|
|
|
buffer := make([]byte, 1024)
|
|
for {
|
|
n, addr, err := sock.ReadFrom(buffer)
|
|
if err != nil {
|
|
log.Fatalf("Error from ReadFrom(): %s", err)
|
|
}
|
|
sock.SetWriteDeadline(time.Now().Add(1 * time.Minute))
|
|
n, err = sock.WriteTo(buffer[0:n], addr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleConnection(conn net.Conn) {
|
|
conn.SetReadDeadline(time.Now().Add(1 * time.Minute))
|
|
content, err := bufio.NewReader(conn).ReadString('\n')
|
|
if err != nil && err != io.EOF {
|
|
fmt.Fprint(os.Stderr, err.Error())
|
|
return
|
|
}
|
|
|
|
conn.SetWriteDeadline(time.Now().Add(1 * time.Minute))
|
|
if _, err = conn.Write([]byte(strings.TrimSuffix(content, "\n"))); err != nil {
|
|
fmt.Fprint(os.Stderr, err.Error())
|
|
return
|
|
}
|
|
|
|
if err = conn.Close(); err != nil {
|
|
fmt.Fprint(os.Stderr, err.Error())
|
|
return
|
|
}
|
|
}
|