1
2
3
4
19
20 package conntrack
21
22 import (
23 "fmt"
24 "strconv"
25 "strings"
26
27 v1 "k8s.io/api/core/v1"
28 "k8s.io/klog/v2"
29 "k8s.io/utils/exec"
30 utilnet "k8s.io/utils/net"
31 )
32
33
34 type Interface interface {
35
36
37 ClearEntriesForIP(ip string, protocol v1.Protocol) error
38
39
40
41 ClearEntriesForPort(port int, isIPv6 bool, protocol v1.Protocol) error
42
43
44
45 ClearEntriesForNAT(origin, dest string, protocol v1.Protocol) error
46
47
48
49 ClearEntriesForPortNAT(dest string, port int, protocol v1.Protocol) error
50 }
51
52
53 type execCT struct {
54 execer exec.Interface
55 }
56
57 var _ Interface = &execCT{}
58
59 func NewExec(execer exec.Interface) Interface {
60 return &execCT{execer: execer}
61 }
62
63
64 const noConnectionToDelete = "0 flow entries have been deleted"
65
66 func protoStr(proto v1.Protocol) string {
67 return strings.ToLower(string(proto))
68 }
69
70 func parametersWithFamily(isIPv6 bool, parameters ...string) []string {
71 if isIPv6 {
72 parameters = append(parameters, "-f", "ipv6")
73 }
74 return parameters
75 }
76
77
78 func (ct *execCT) exec(parameters ...string) error {
79 conntrackPath, err := ct.execer.LookPath("conntrack")
80 if err != nil {
81 return fmt.Errorf("error looking for path of conntrack: %v", err)
82 }
83 klog.V(4).InfoS("Clearing conntrack entries", "parameters", parameters)
84 output, err := ct.execer.Command(conntrackPath, parameters...).CombinedOutput()
85 if err != nil {
86 return fmt.Errorf("conntrack command returned: %q, error message: %s", string(output), err)
87 }
88 klog.V(4).InfoS("Conntrack entries deleted", "output", string(output))
89 return nil
90 }
91
92
93 func (ct *execCT) ClearEntriesForIP(ip string, protocol v1.Protocol) error {
94 parameters := parametersWithFamily(utilnet.IsIPv6String(ip), "-D", "--orig-dst", ip, "-p", protoStr(protocol))
95 err := ct.exec(parameters...)
96 if err != nil && !strings.Contains(err.Error(), noConnectionToDelete) {
97
98
99
100 return fmt.Errorf("error deleting connection tracking state for UDP service IP: %s, error: %v", ip, err)
101 }
102 return nil
103 }
104
105
106 func (ct *execCT) ClearEntriesForPort(port int, isIPv6 bool, protocol v1.Protocol) error {
107 if port <= 0 {
108 return fmt.Errorf("wrong port number. The port number must be greater than zero")
109 }
110 parameters := parametersWithFamily(isIPv6, "-D", "-p", protoStr(protocol), "--dport", strconv.Itoa(port))
111 err := ct.exec(parameters...)
112 if err != nil && !strings.Contains(err.Error(), noConnectionToDelete) {
113 return fmt.Errorf("error deleting conntrack entries for UDP port: %d, error: %v", port, err)
114 }
115 return nil
116 }
117
118
119 func (ct *execCT) ClearEntriesForNAT(origin, dest string, protocol v1.Protocol) error {
120 parameters := parametersWithFamily(utilnet.IsIPv6String(origin), "-D", "--orig-dst", origin, "--dst-nat", dest,
121 "-p", protoStr(protocol))
122 err := ct.exec(parameters...)
123 if err != nil && !strings.Contains(err.Error(), noConnectionToDelete) {
124
125
126
127 return fmt.Errorf("error deleting conntrack entries for UDP peer {%s, %s}, error: %v", origin, dest, err)
128 }
129 return nil
130 }
131
132
133 func (ct *execCT) ClearEntriesForPortNAT(dest string, port int, protocol v1.Protocol) error {
134 if port <= 0 {
135 return fmt.Errorf("wrong port number. The port number must be greater than zero")
136 }
137 parameters := parametersWithFamily(utilnet.IsIPv6String(dest), "-D", "-p", protoStr(protocol), "--dport", strconv.Itoa(port), "--dst-nat", dest)
138 err := ct.exec(parameters...)
139 if err != nil && !strings.Contains(err.Error(), noConnectionToDelete) {
140 return fmt.Errorf("error deleting conntrack entries for UDP port: %d, error: %v", port, err)
141 }
142 return nil
143 }
144
View as plain text