This repository has been archived by the owner on Jul 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 276
/
Copy pathiptables.go
162 lines (131 loc) · 7.52 KB
/
iptables.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package injector
import (
"fmt"
"strconv"
"strings"
configv1alpha2 "github.com/openservicemesh/osm/pkg/apis/config/v1alpha2"
"github.com/openservicemesh/osm/pkg/constants"
)
// iptablesOutboundStaticRules is the list of iptables rules related to outbound traffic interception and redirection
var iptablesOutboundStaticRules = []string{
// Redirects outbound TCP traffic hitting OSM_PROXY_OUT_REDIRECT chain to Envoy's outbound listener port
fmt.Sprintf("-A OSM_PROXY_OUT_REDIRECT -p tcp -j REDIRECT --to-port %d", constants.EnvoyOutboundListenerPort),
// Traffic to the Proxy Admin port flows to the Proxy -- not redirected
fmt.Sprintf("-A OSM_PROXY_OUT_REDIRECT -p tcp --dport %d -j ACCEPT", constants.EnvoyAdminPort),
// For outbound TCP traffic jump from OUTPUT chain to OSM_PROXY_OUTBOUND chain
"-A OUTPUT -p tcp -j OSM_PROXY_OUTBOUND",
// Outbound traffic from Envoy to the local app over the loopback interface should jump to the inbound proxy redirect chain.
// So when an app directs traffic to itself via the k8s service, traffic flows as follows:
// app -> local envoy's outbound listener -> iptables -> local envoy's inbound listener -> app
fmt.Sprintf("-A OSM_PROXY_OUTBOUND -o lo ! -d 127.0.0.1/32 -m owner --uid-owner %d -j OSM_PROXY_IN_REDIRECT", constants.EnvoyUID),
// Outbound traffic from the app to itself over the loopback interface is not be redirected via the proxy.
// E.g. when app sends traffic to itself via the pod IP.
fmt.Sprintf("-A OSM_PROXY_OUTBOUND -o lo -m owner ! --uid-owner %d -j RETURN", constants.EnvoyUID),
// Don't redirect Envoy traffic back to itself, return it to the next chain for processing
fmt.Sprintf("-A OSM_PROXY_OUTBOUND -m owner --uid-owner %d -j RETURN", constants.EnvoyUID),
// Skip localhost traffic, doesn't need to be routed via the proxy
"-A OSM_PROXY_OUTBOUND -d 127.0.0.1/32 -j RETURN",
}
// iptablesInboundStaticRules is the list of iptables rules related to inbound traffic interception and redirection
var iptablesInboundStaticRules = []string{
// Redirects inbound TCP traffic hitting the OSM_PROXY_IN_REDIRECT chain to Envoy's inbound listener port
fmt.Sprintf("-A OSM_PROXY_IN_REDIRECT -p tcp -j REDIRECT --to-port %d", constants.EnvoyInboundListenerPort),
// For inbound traffic jump from PREROUTING chain to OSM_PROXY_INBOUND chain
"-A PREROUTING -p tcp -j OSM_PROXY_INBOUND",
// Skip metrics query traffic being directed to Envoy's inbound prometheus listener port
fmt.Sprintf("-A OSM_PROXY_INBOUND -p tcp --dport %d -j RETURN", constants.EnvoyPrometheusInboundListenerPort),
// Skip inbound health probes; These ports will be explicitly handled by listeners configured on the
// Envoy proxy IF any health probes have been configured in the Pod Spec.
// TODO(draychev): Do not add these if no health probes have been defined (https://github.com/openservicemesh/osm/issues/2243)
fmt.Sprintf("-A OSM_PROXY_INBOUND -p tcp --dport %d -j RETURN", constants.LivenessProbePort),
fmt.Sprintf("-A OSM_PROXY_INBOUND -p tcp --dport %d -j RETURN", constants.ReadinessProbePort),
fmt.Sprintf("-A OSM_PROXY_INBOUND -p tcp --dport %d -j RETURN", constants.StartupProbePort),
// Skip inbound health probes (originally TCPSocket health probes); requests handled by osm-healthcheck
fmt.Sprintf("-A OSM_PROXY_INBOUND -p tcp --dport %d -j RETURN", constants.HealthcheckPort),
// Redirect remaining inbound traffic to Envoy
"-A OSM_PROXY_INBOUND -p tcp -j OSM_PROXY_IN_REDIRECT",
}
// generateIptablesCommands generates a list of iptables commands to set up sidecar interception and redirection
func generateIptablesCommands(proxyMode configv1alpha2.LocalProxyMode, outboundIPRangeExclusionList []string, outboundIPRangeInclusionList []string, outboundPortExclusionList []int, inboundPortExclusionList []int, networkInterfaceExclusionList []string) string {
var rules strings.Builder
fmt.Fprintln(&rules, `# OSM sidecar interception rules
*nat
:OSM_PROXY_INBOUND - [0:0]
:OSM_PROXY_IN_REDIRECT - [0:0]
:OSM_PROXY_OUTBOUND - [0:0]
:OSM_PROXY_OUT_REDIRECT - [0:0]`)
var cmds []string
// 1. Create inbound rules
cmds = append(cmds, iptablesInboundStaticRules...)
// Ignore inbound traffic on specified interfaces
for _, iface := range networkInterfaceExclusionList {
// *Note: it is important to use the insert option '-I' instead of the append option '-A' to ensure the
// exclusion of traffic to the network interface happens before the rule that redirects traffic to the proxy
cmds = append(cmds, fmt.Sprintf("-I OSM_PROXY_INBOUND -i %s -j RETURN", iface))
}
// 2. Create dynamic inbound ports exclusion rules
if len(inboundPortExclusionList) > 0 {
var portExclusionListStr []string
for _, port := range inboundPortExclusionList {
portExclusionListStr = append(portExclusionListStr, strconv.Itoa(port))
}
inboundPortsToExclude := strings.Join(portExclusionListStr, ",")
rule := fmt.Sprintf("-I OSM_PROXY_INBOUND -p tcp --match multiport --dports %s -j RETURN", inboundPortsToExclude)
cmds = append(cmds, rule)
}
// 3. Create outbound rules
cmds = append(cmds, iptablesOutboundStaticRules...)
if proxyMode == configv1alpha2.LocalProxyModePodIP {
// For envoy -> local service container proxying, send traffic to pod IP instead of localhost
// *Note: it is important to use the insert option '-I' instead of the append option '-A' to ensure the
// DNAT to the pod ip for envoy -> localhost traffic happens before the rule that redirects traffic to the proxy
cmds = append(cmds, fmt.Sprintf("-I OUTPUT -p tcp -o lo -d 127.0.0.1/32 -m owner --uid-owner %d -j DNAT --to-destination $POD_IP", constants.EnvoyUID))
}
// Ignore outbound traffic in specified interfaces
for _, iface := range networkInterfaceExclusionList {
cmds = append(cmds, fmt.Sprintf("-A OSM_PROXY_OUTBOUND -o %s -j RETURN", iface))
}
//
// Create outbound exclusion and inclusion rules.
// *Note: exclusion rules must be applied before inclusions as order matters
//
// 4. Create dynamic outbound IP range exclusion rules
for _, cidr := range outboundIPRangeExclusionList {
// *Note: it is important to use the insert option '-I' instead of the append option '-A' to ensure the exclusion
// rules take precedence over the static redirection rules. Iptables rules are evaluated in order.
rule := fmt.Sprintf("-A OSM_PROXY_OUTBOUND -d %s -j RETURN", cidr)
cmds = append(cmds, rule)
}
// 5. Create dynamic outbound ports exclusion rules
if len(outboundPortExclusionList) > 0 {
var portExclusionListStr []string
for _, port := range outboundPortExclusionList {
portExclusionListStr = append(portExclusionListStr, strconv.Itoa(port))
}
outboundPortsToExclude := strings.Join(portExclusionListStr, ",")
rule := fmt.Sprintf("-A OSM_PROXY_OUTBOUND -p tcp --match multiport --dports %s -j RETURN", outboundPortsToExclude)
cmds = append(cmds, rule)
}
// 6. Create dynamic outbound IP range inclusion rules
if len(outboundIPRangeInclusionList) > 0 {
// Redirect specified IP ranges to the proxy
for _, cidr := range outboundIPRangeInclusionList {
rule := fmt.Sprintf("-A OSM_PROXY_OUTBOUND -d %s -j OSM_PROXY_OUT_REDIRECT", cidr)
cmds = append(cmds, rule)
}
// Remaining traffic not belonging to specified inclusion IP ranges are not redirected
cmds = append(cmds, "-A OSM_PROXY_OUTBOUND -j RETURN")
} else {
// Redirect remaining outbound traffic to the proxy
cmds = append(cmds, "-A OSM_PROXY_OUTBOUND -j OSM_PROXY_OUT_REDIRECT")
}
for _, rule := range cmds {
fmt.Fprintln(&rules, rule)
}
fmt.Fprint(&rules, "COMMIT")
cmd := fmt.Sprintf(`iptables-restore --noflush <<EOF
%s
EOF
`, rules.String())
return cmd
}