forked from cilium/cilium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dns.go
153 lines (134 loc) · 5.04 KB
/
dns.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
// Copyright 2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package proxy
import (
"fmt"
"strings"
"github.com/cilium/cilium/pkg/completion"
"github.com/cilium/cilium/pkg/fqdn/dnsproxy"
"github.com/cilium/cilium/pkg/fqdn/matchpattern"
"github.com/cilium/cilium/pkg/logging/logfields"
"github.com/cilium/cilium/pkg/policy"
"github.com/cilium/cilium/pkg/proxy/logger"
"github.com/cilium/cilium/pkg/revert"
"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)
var (
// DefaultDNSProxy is the global, shared, DNS Proxy singleton.
DefaultDNSProxy *dnsproxy.DNSProxy
)
// dnsRedirect implements the Redirect interface for an l7 proxy
type dnsRedirect struct {
redirect *Redirect
endpointInfoRegistry logger.EndpointInfoRegistry
conf dnsConfiguration
DNSProxyPort uint16
currentRules policy.L7DataMap
}
type dnsConfiguration struct {
}
// setRules replaces old l7 rules of a redirect with new ones.
func (dr *dnsRedirect) setRules(wg *completion.WaitGroup, newRules policy.L7DataMap) error {
var toRemove, toAdd []string
for _, rule := range dr.currentRules {
for _, dnsRule := range rule.DNS {
if len(dnsRule.MatchName) > 0 {
dnsName := strings.ToLower(dns.Fqdn(dnsRule.MatchName))
dnsNameAsRE := matchpattern.ToRegexp(dnsName)
toRemove = append(toRemove, dnsNameAsRE)
}
if len(dnsRule.MatchPattern) > 0 {
dnsPattern := matchpattern.Sanitize(dnsRule.MatchPattern)
dnsPatternAsRE := matchpattern.ToRegexp(dnsPattern)
toRemove = append(toRemove, dnsPatternAsRE)
}
}
}
for _, rule := range dr.redirect.rules {
for _, dnsRule := range rule.DNS {
if len(dnsRule.MatchName) > 0 {
dnsName := strings.ToLower(dns.Fqdn(dnsRule.MatchName))
dnsNameAsRE := matchpattern.ToRegexp(dnsName)
toAdd = append(toAdd, dnsNameAsRE)
}
if len(dnsRule.MatchPattern) > 0 {
dnsPattern := matchpattern.Sanitize(dnsRule.MatchPattern)
dnsPatternAsRE := matchpattern.ToRegexp(dnsPattern)
toAdd = append(toAdd, dnsPatternAsRE)
}
}
}
log.WithFields(logrus.Fields{
"add": toAdd,
"remove": toRemove,
logfields.EndpointID: dr.redirect.endpointID,
}).Debug("DNS Proxy updating matchNames in allowed list during UpdateRules")
DefaultDNSProxy.UpdateAllowed(toAdd, toRemove, fmt.Sprintf("%d", dr.redirect.endpointID))
dr.currentRules = copyRules(dr.redirect.rules)
return nil
}
// UpdateRules atomically replaces the proxy rules in effect for this redirect.
// It is not aware of revision number and doesn't account for out-of-order
// calls to UpdateRules or the returned RevertFunc.
func (dr *dnsRedirect) UpdateRules(wg *completion.WaitGroup, l4 *policy.L4Filter) (revert.RevertFunc, error) {
oldRules := dr.currentRules
err := dr.setRules(wg, dr.redirect.rules)
revertFunc := func() error {
return dr.setRules(nil, oldRules)
}
return revertFunc, err
}
// Close the redirect.
func (dr *dnsRedirect) Close(wg *completion.WaitGroup) (revert.FinalizeFunc, revert.RevertFunc) {
return func() {
for _, rule := range dr.currentRules {
for _, dnsRule := range rule.DNS {
dnsName := strings.ToLower(dns.Fqdn(dnsRule.MatchName))
dnsNameAsRE := matchpattern.ToRegexp(dnsName)
DefaultDNSProxy.RemoveAllowed(dnsNameAsRE, fmt.Sprintf("%d", dr.redirect.endpointID))
dnsPattern := matchpattern.Sanitize(dnsRule.MatchPattern)
dnsPatternAsRE := matchpattern.ToRegexp(dnsPattern)
DefaultDNSProxy.RemoveAllowed(dnsPatternAsRE, fmt.Sprintf("%d", dr.redirect.endpointID))
}
}
dr.currentRules = nil
}, nil
}
// creatednsRedirect creates a redirect to the dns proxy. The redirect structure passed
// in is safe to access for reading and writing.
func createDNSRedirect(r *Redirect, conf dnsConfiguration, endpointInfoRegistry logger.EndpointInfoRegistry) (RedirectImplementation, error) {
dr := &dnsRedirect{
redirect: r,
conf: conf,
endpointInfoRegistry: endpointInfoRegistry,
// NOTE: We use a fixed port here but a port was given to us in r. It's
// unclear who will release it, nor if this global port will be released
// when any DNS rule is removed. We rely on that happening elsewhere.
DNSProxyPort: DefaultDNSProxy.BindPort,
}
r.ProxyPort = dr.DNSProxyPort
log.WithFields(logrus.Fields{
"dnsRedirect": dr,
"conf": conf,
}).Debug("Creating DNS Proxy redirect")
return dr, dr.setRules(nil, r.rules)
}
func copyRules(rules policy.L7DataMap) policy.L7DataMap {
currentRules := policy.L7DataMap{}
for key, val := range rules {
currentRules[key] = val
}
return currentRules
}