istio

Форк
0
/
iptables_builder_impl.go 
246 строк · 8.2 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package builder
16

17
import (
18
	"fmt"
19
	"strings"
20

21
	"istio.io/istio/pkg/util/sets"
22
	"istio.io/istio/tools/istio-iptables/pkg/config"
23
	"istio.io/istio/tools/istio-iptables/pkg/constants"
24
	"istio.io/istio/tools/istio-iptables/pkg/log"
25
)
26

27
// Rule represents iptables rule - chain, table and options
28
type Rule struct {
29
	chain  string
30
	table  string
31
	params []string
32
}
33

34
// Rules represents iptables for V4 and V6
35
type Rules struct {
36
	rulesv4 []*Rule
37
	rulesv6 []*Rule
38
}
39

40
// IptablesRuleBuilder is an implementation for IptablesRuleBuilder interface
41
type IptablesRuleBuilder struct {
42
	rules Rules
43
	cfg   *config.Config
44
}
45

46
// NewIptablesBuilders creates a new IptablesRuleBuilder
47
func NewIptablesRuleBuilder(cfg *config.Config) *IptablesRuleBuilder {
48
	if cfg == nil {
49
		cfg = &config.Config{}
50
	}
51
	return &IptablesRuleBuilder{
52
		rules: Rules{
53
			rulesv4: []*Rule{},
54
			rulesv6: []*Rule{},
55
		},
56
		cfg: cfg,
57
	}
58
}
59

60
func (rb *IptablesRuleBuilder) InsertRule(command log.Command, chain string, table string, position int, params ...string) *IptablesRuleBuilder {
61
	rb.InsertRuleV4(command, chain, table, position, params...)
62
	rb.InsertRuleV6(command, chain, table, position, params...)
63
	return rb
64
}
65

66
// nolint lll
67
func (rb *IptablesRuleBuilder) insertInternal(ipt *[]*Rule, command log.Command, chain string, table string, position int, params ...string) *IptablesRuleBuilder {
68
	rules := params
69
	*ipt = append(*ipt, &Rule{
70
		chain:  chain,
71
		table:  table,
72
		params: append([]string{"-I", chain, fmt.Sprint(position)}, rules...),
73
	})
74
	idx := indexOf("-j", params)
75
	// We have identified the type of command this is and logging is enabled. Insert a rule to log this chain was hit.
76
	// Since this is insert we do this *after* the real chain, which will result in it bumping it forward
77
	if rb.cfg.TraceLogging && idx >= 0 && command != log.UndefinedCommand {
78
		match := params[:idx]
79
		// 1337 group is just a random constant to be matched on the log reader side
80
		// Size of 20 allows reading the IPv4 IP header.
81
		match = append(match, "-j", "NFLOG", "--nflog-prefix", fmt.Sprintf(`%q`, command.Identifier), "--nflog-group", "1337", "--nflog-size", "20")
82
		*ipt = append(*ipt, &Rule{
83
			chain:  chain,
84
			table:  table,
85
			params: append([]string{"-I", chain, fmt.Sprint(position)}, match...),
86
		})
87
	}
88
	return rb
89
}
90

91
func (rb *IptablesRuleBuilder) InsertRuleV4(command log.Command, chain string, table string, position int, params ...string) *IptablesRuleBuilder {
92
	return rb.insertInternal(&rb.rules.rulesv4, command, chain, table, position, params...)
93
}
94

95
func (rb *IptablesRuleBuilder) InsertRuleV6(command log.Command, chain string, table string, position int, params ...string) *IptablesRuleBuilder {
96
	if !rb.cfg.EnableInboundIPv6 {
97
		return rb
98
	}
99
	return rb.insertInternal(&rb.rules.rulesv6, command, chain, table, position, params...)
100
}
101

102
func indexOf(element string, data []string) int {
103
	for k, v := range data {
104
		if element == v {
105
			return k
106
		}
107
	}
108
	return -1 // not found.
109
}
110

111
func (rb *IptablesRuleBuilder) appendInternal(ipt *[]*Rule, command log.Command, chain string, table string, params ...string) *IptablesRuleBuilder {
112
	idx := indexOf("-j", params)
113
	// We have identified the type of command this is and logging is enabled. Appending a rule to log this chain will be hit
114
	if rb.cfg.TraceLogging && idx >= 0 && command != log.UndefinedCommand {
115
		match := params[:idx]
116
		// 1337 group is just a random constant to be matched on the log reader side
117
		// Size of 20 allows reading the IPv4 IP header.
118
		match = append(match, "-j", "NFLOG", "--nflog-prefix", fmt.Sprintf(`%q`, command.Identifier), "--nflog-group", "1337", "--nflog-size", "20")
119
		*ipt = append(*ipt, &Rule{
120
			chain:  chain,
121
			table:  table,
122
			params: append([]string{"-A", chain}, match...),
123
		})
124
	}
125
	rules := params
126
	*ipt = append(*ipt, &Rule{
127
		chain:  chain,
128
		table:  table,
129
		params: append([]string{"-A", chain}, rules...),
130
	})
131
	return rb
132
}
133

134
func (rb *IptablesRuleBuilder) AppendRuleV4(command log.Command, chain string, table string, params ...string) *IptablesRuleBuilder {
135
	return rb.appendInternal(&rb.rules.rulesv4, command, chain, table, params...)
136
}
137

138
func (rb *IptablesRuleBuilder) AppendRule(command log.Command, chain string, table string, params ...string) *IptablesRuleBuilder {
139
	rb.AppendRuleV4(command, chain, table, params...)
140
	rb.AppendRuleV6(command, chain, table, params...)
141
	return rb
142
}
143

144
func (rb *IptablesRuleBuilder) AppendRuleV6(command log.Command, chain string, table string, params ...string) *IptablesRuleBuilder {
145
	if !rb.cfg.EnableInboundIPv6 {
146
		return rb
147
	}
148
	return rb.appendInternal(&rb.rules.rulesv6, command, chain, table, params...)
149
}
150

151
func (rb *IptablesRuleBuilder) buildRules(rules []*Rule) [][]string {
152
	output := make([][]string, 0)
153
	chainTableLookupSet := sets.New[string]()
154
	for _, r := range rules {
155
		chainTable := fmt.Sprintf("%s:%s", r.chain, r.table)
156
		// Create new chain if key: `chainTable` isn't present in map
157
		if !chainTableLookupSet.Contains(chainTable) {
158
			// Ignore chain creation for built-in chains for iptables
159
			if _, present := constants.BuiltInChainsMap[r.chain]; !present {
160
				cmd := []string{"-t", r.table, "-N", r.chain}
161
				output = append(output, cmd)
162
				chainTableLookupSet.Insert(chainTable)
163
			}
164
		}
165
	}
166
	for _, r := range rules {
167
		cmd := append([]string{"-t", r.table}, r.params...)
168
		output = append(output, cmd)
169
	}
170
	return output
171
}
172

173
func (rb *IptablesRuleBuilder) BuildV4() [][]string {
174
	return rb.buildRules(rb.rules.rulesv4)
175
}
176

177
func (rb *IptablesRuleBuilder) BuildV6() [][]string {
178
	return rb.buildRules(rb.rules.rulesv6)
179
}
180

181
func (rb *IptablesRuleBuilder) constructIptablesRestoreContents(tableRulesMap map[string][]string) string {
182
	var b strings.Builder
183
	for table, rules := range tableRulesMap {
184
		if len(rules) > 0 {
185
			_, _ = fmt.Fprintln(&b, "*", table)
186
			for _, r := range rules {
187
				_, _ = fmt.Fprintln(&b, r)
188
			}
189
			_, _ = fmt.Fprintln(&b, "COMMIT")
190
		}
191
	}
192
	return b.String()
193
}
194

195
func (rb *IptablesRuleBuilder) buildRestore(rules []*Rule) string {
196
	tableRulesMap := map[string][]string{
197
		constants.FILTER: {},
198
		constants.NAT:    {},
199
		constants.MANGLE: {},
200
	}
201

202
	chainTableLookupMap := sets.New[string]()
203
	for _, r := range rules {
204
		chainTable := fmt.Sprintf("%s:%s", r.chain, r.table)
205
		// Create new chain if key: `chainTable` isn't present in map
206
		if !chainTableLookupMap.Contains(chainTable) {
207
			// Ignore chain creation for built-in chains for iptables
208
			if _, present := constants.BuiltInChainsMap[r.chain]; !present {
209
				tableRulesMap[r.table] = append(tableRulesMap[r.table], fmt.Sprintf("-N %s", r.chain))
210
				chainTableLookupMap.Insert(chainTable)
211
			}
212
		}
213
	}
214

215
	for _, r := range rules {
216
		tableRulesMap[r.table] = append(tableRulesMap[r.table], strings.Join(r.params, " "))
217
	}
218
	return rb.constructIptablesRestoreContents(tableRulesMap)
219
}
220

221
func (rb *IptablesRuleBuilder) BuildV4Restore() string {
222
	return rb.buildRestore(rb.rules.rulesv4)
223
}
224

225
func (rb *IptablesRuleBuilder) BuildV6Restore() string {
226
	return rb.buildRestore(rb.rules.rulesv6)
227
}
228

229
// AppendVersionedRule is a wrapper around AppendRule that substitutes an ipv4/ipv6 specific value
230
// in place in the params. This allows appending a dual-stack rule that has an IP value in it.
231
func (rb *IptablesRuleBuilder) AppendVersionedRule(ipv4 string, ipv6 string, command log.Command, chain string, table string, params ...string) {
232
	rb.AppendRuleV4(command, chain, table, replaceVersionSpecific(ipv4, params...)...)
233
	rb.AppendRuleV6(command, chain, table, replaceVersionSpecific(ipv6, params...)...)
234
}
235

236
func replaceVersionSpecific(contents string, inputs ...string) []string {
237
	res := make([]string, 0, len(inputs))
238
	for _, i := range inputs {
239
		if i == constants.IPVersionSpecific {
240
			res = append(res, contents)
241
		} else {
242
			res = append(res, i)
243
		}
244
	}
245
	return res
246
}
247

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.