mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-23 13:59:09 +02:00
Address review comments
This commit is contained in:
@@ -43,6 +43,7 @@ func ParseLevel(s string) Level {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the wire form of the level: "default" or "strict".
|
||||||
func (l Level) String() string {
|
func (l Level) String() string {
|
||||||
if l >= LevelStrict {
|
if l >= LevelStrict {
|
||||||
return "strict"
|
return "strict"
|
||||||
@@ -67,17 +68,20 @@ var (
|
|||||||
type Anonymizer struct {
|
type Anonymizer struct {
|
||||||
ipAnonymizer map[netip.Addr]netip.Addr
|
ipAnonymizer map[netip.Addr]netip.Addr
|
||||||
domainAnonymizer map[string]string
|
domainAnonymizer map[string]string
|
||||||
labelAnonymizer map[string]string
|
// domainOrder caches the keys of domainAnonymizer sorted longest-first
|
||||||
labelAnonymized map[string]struct{}
|
// for AnonymizeString; it is rebuilt when the map gains entries.
|
||||||
labelCounter uint32
|
domainOrder []string
|
||||||
macAnonymizer map[string]string
|
labelAnonymizer map[string]string
|
||||||
macCounter uint32
|
labelAnonymized map[string]struct{}
|
||||||
wgKeyAnonymizer map[string]string
|
labelCounter uint32
|
||||||
wgKeyAnonymized map[string]struct{}
|
macAnonymizer map[string]string
|
||||||
currentAnonIPv4 netip.Addr
|
macCounter uint32
|
||||||
currentAnonIPv6 netip.Addr
|
wgKeyAnonymizer map[string]string
|
||||||
startAnonIPv4 netip.Addr
|
wgKeyAnonymized map[string]struct{}
|
||||||
startAnonIPv6 netip.Addr
|
currentAnonIPv4 netip.Addr
|
||||||
|
currentAnonIPv6 netip.Addr
|
||||||
|
startAnonIPv4 netip.Addr
|
||||||
|
startAnonIPv6 netip.Addr
|
||||||
|
|
||||||
// LevelStrict also anonymizes internal ranges (RFC 1918, CGNAT,
|
// LevelStrict also anonymizes internal ranges (RFC 1918, CGNAT,
|
||||||
// link-local), replacing them from the dedicated internal pools below so
|
// link-local), replacing them from the dedicated internal pools below so
|
||||||
@@ -136,6 +140,10 @@ func (a *Anonymizer) SetLevel(level Level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Anonymizer) AnonymizeIP(ip netip.Addr) netip.Addr {
|
func (a *Anonymizer) AnonymizeIP(ip netip.Addr) netip.Addr {
|
||||||
|
// Normalize 4-in-6 addresses so ::ffff:192.168.1.1 classifies and maps
|
||||||
|
// like 192.168.1.1.
|
||||||
|
ip = ip.Unmap()
|
||||||
|
|
||||||
if ip.IsLoopback() ||
|
if ip.IsLoopback() ||
|
||||||
ip.IsUnspecified() ||
|
ip.IsUnspecified() ||
|
||||||
ip.IsMulticast() ||
|
ip.IsMulticast() ||
|
||||||
@@ -393,19 +401,7 @@ func (a *Anonymizer) AnonymizeString(str string) string {
|
|||||||
str = ipv4Regex.ReplaceAllStringFunc(str, a.AnonymizeIPString)
|
str = ipv4Regex.ReplaceAllStringFunc(str, a.AnonymizeIPString)
|
||||||
str = ipv6Regex.ReplaceAllStringFunc(str, a.AnonymizeIPString)
|
str = ipv6Regex.ReplaceAllStringFunc(str, a.AnonymizeIPString)
|
||||||
|
|
||||||
// Longest mappings first, so a full-FQDN mapping (strict level) is applied
|
for _, domain := range a.sortedDomains() {
|
||||||
// before the base-domain mapping it contains.
|
|
||||||
domains := make([]string, 0, len(a.domainAnonymizer))
|
|
||||||
for domain := range a.domainAnonymizer {
|
|
||||||
domains = append(domains, domain)
|
|
||||||
}
|
|
||||||
slices.SortFunc(domains, func(x, y string) int {
|
|
||||||
if d := len(y) - len(x); d != 0 {
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
return strings.Compare(x, y)
|
|
||||||
})
|
|
||||||
for _, domain := range domains {
|
|
||||||
str = strings.ReplaceAll(str, domain, a.domainAnonymizer[domain])
|
str = strings.ReplaceAll(str, domain, a.domainAnonymizer[domain])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +421,27 @@ func (a *Anonymizer) AnonymizeString(str string) string {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sortedDomains returns the domain mappings longest-first, so a full-FQDN
|
||||||
|
// mapping (strict level) is applied before the base-domain mapping it
|
||||||
|
// contains. The order is rebuilt only when domainAnonymizer has grown.
|
||||||
|
func (a *Anonymizer) sortedDomains() []string {
|
||||||
|
if len(a.domainOrder) == len(a.domainAnonymizer) {
|
||||||
|
return a.domainOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
a.domainOrder = a.domainOrder[:0]
|
||||||
|
for domain := range a.domainAnonymizer {
|
||||||
|
a.domainOrder = append(a.domainOrder, domain)
|
||||||
|
}
|
||||||
|
slices.SortFunc(a.domainOrder, func(x, y string) int {
|
||||||
|
if d := len(y) - len(x); d != 0 {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
return strings.Compare(x, y)
|
||||||
|
})
|
||||||
|
return a.domainOrder
|
||||||
|
}
|
||||||
|
|
||||||
// anonymizeMACsInString replaces MAC addresses matched by re, skipping
|
// anonymizeMACsInString replaces MAC addresses matched by re, skipping
|
||||||
// matches that directly adjoin another sep so a six-group run inside a longer
|
// matches that directly adjoin another sep so a six-group run inside a longer
|
||||||
// separated sequence is left alone.
|
// separated sequence is left alone.
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ func TestAnonymizeIP_DefaultLevelInternalRanges(t *testing.T) {
|
|||||||
// ULA is anonymized even at the default level: its random global ID
|
// ULA is anonymized even at the default level: its random global ID
|
||||||
// uniquely fingerprints the network, unlike shared RFC 1918 space.
|
// uniquely fingerprints the network, unlike shared RFC 1918 space.
|
||||||
{"IPv6 ULA", "fd12:3456:789a::1", "2001:db8:ffff::"},
|
{"IPv6 ULA", "fd12:3456:789a::1", "2001:db8:ffff::"},
|
||||||
|
// 4-in-6 addresses classify like their unmapped IPv4 form.
|
||||||
|
{"4-in-6 RFC1918", "::ffff:192.168.1.1", "192.168.1.1"},
|
||||||
|
{"4-in-6 CGNAT", "::ffff:100.64.0.5", "100.64.0.5"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@@ -124,6 +127,7 @@ func TestAnonymizeIP_StrictLevel(t *testing.T) {
|
|||||||
{"Well known split marker", "128.0.0.0", "128.0.0.0"},
|
{"Well known split marker", "128.0.0.0", "128.0.0.0"},
|
||||||
{"In internal pool range", "198.18.0.3", "198.18.0.3"},
|
{"In internal pool range", "198.18.0.3", "198.18.0.3"},
|
||||||
{"In public pool range", "198.51.100.0", "198.51.100.0"},
|
{"In public pool range", "198.51.100.0", "198.51.100.0"},
|
||||||
|
{"4-in-6 repeated RFC1918", "::ffff:192.168.1.1", "198.18.0.0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ func (g *BundleGenerator) toWGShowFormat(s *configurer.Stats) string {
|
|||||||
if len(peer.AllowedIPs) > 0 {
|
if len(peer.AllowedIPs) > 0 {
|
||||||
var ipStrings []string
|
var ipStrings []string
|
||||||
for _, ipnet := range peer.AllowedIPs {
|
for _, ipnet := range peer.AllowedIPs {
|
||||||
ipStrings = append(ipStrings, ipnet.String())
|
ipStr := ipnet.String()
|
||||||
|
if g.anonymize {
|
||||||
|
ipStr = g.anonymizer.AnonymizeIPString(ipStr)
|
||||||
|
}
|
||||||
|
ipStrings = append(ipStrings, ipStr)
|
||||||
}
|
}
|
||||||
sb.WriteString(fmt.Sprintf(" allowed ips: %s\n", strings.Join(ipStrings, ", ")))
|
sb.WriteString(fmt.Sprintf(" allowed ips: %s\n", strings.Join(ipStrings, ", ")))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1013,7 +1013,6 @@ func anonymizeOverview(a *anonymize.Anonymizer, overview *OutputOverview) {
|
|||||||
overview.SignalState.Error = a.AnonymizeString(overview.SignalState.Error)
|
overview.SignalState.Error = a.AnonymizeString(overview.SignalState.Error)
|
||||||
|
|
||||||
overview.PubKey = a.AnonymizeWGKey(overview.PubKey)
|
overview.PubKey = a.AnonymizeWGKey(overview.PubKey)
|
||||||
overview.FQDN = a.AnonymizeDomain(overview.FQDN)
|
|
||||||
overview.IP = a.AnonymizeIPString(overview.IP)
|
overview.IP = a.AnonymizeIPString(overview.IP)
|
||||||
overview.IPv6 = a.AnonymizeIPString(overview.IPv6)
|
overview.IPv6 = a.AnonymizeIPString(overview.IPv6)
|
||||||
for i, detail := range overview.Relays.Details {
|
for i, detail := range overview.Relays.Details {
|
||||||
@@ -1034,15 +1033,6 @@ func anonymizeOverview(a *anonymize.Anonymizer, overview *OutputOverview) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, event := range overview.Events {
|
|
||||||
event.Message = a.AnonymizeString(event.Message)
|
|
||||||
event.UserMessage = a.AnonymizeString(event.UserMessage)
|
|
||||||
for k, v := range event.Metadata {
|
|
||||||
event.Metadata[k] = a.AnonymizeString(v)
|
|
||||||
}
|
|
||||||
overview.Events[i] = event
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, route := range overview.Networks {
|
for i, route := range overview.Networks {
|
||||||
overview.Networks[i] = a.AnonymizeRoute(route)
|
overview.Networks[i] = a.AnonymizeRoute(route)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1012,7 +1012,7 @@
|
|||||||
"description": "Helper text under the anonymization dropdown. The level details live in the info tooltip."
|
"description": "Helper text under the anonymization dropdown. The level details live in the info tooltip."
|
||||||
},
|
},
|
||||||
"settings.troubleshooting.anonymize.info": {
|
"settings.troubleshooting.anonymize.info": {
|
||||||
"message": "Default keeps internal IP addresses and peer names readable for support. Strict additionally anonymizes private (RFC 1918), CGNAT, and link-local IP addresses, peer names, and WireGuard public keys. Recurring values map to the same placeholder, so peers stay distinguishable. Use Strict when sharing the bundle outside your organization.",
|
"message": "Default keeps internal IPv4 addresses and peer names readable for support. Strict additionally anonymizes private (RFC 1918), CGNAT, and link-local IP addresses, peer names, and WireGuard public keys. Recurring values map to the same placeholder, so peers stay distinguishable. Use Strict when sharing the bundle outside your organization.",
|
||||||
"description": "Info tooltip explaining the anonymization levels. 'RFC 1918', 'CGNAT', 'link-local', and 'WireGuard' are technical terms — keep them."
|
"description": "Info tooltip explaining the anonymization levels. 'RFC 1918', 'CGNAT', 'link-local', and 'WireGuard' are technical terms — keep them."
|
||||||
},
|
},
|
||||||
"settings.troubleshooting.anonymize.none": {
|
"settings.troubleshooting.anonymize.none": {
|
||||||
|
|||||||
Reference in New Issue
Block a user