55 "fmt"
66 "net/netip"
77 "regexp"
8+ "strings"
89
910 "github.com/miekg/dns"
1011 "github.com/qdm12/gosettings/validate"
@@ -22,6 +23,10 @@ type Settings struct {
2223 // FqdnExemptFromRebindingProtection is a list of
2324 // fully qualified domain names that are exempt from rebinding protection.
2425 FqdnExemptFromRebindingProtection []string
26+ // ParentsExemptFromRebindingProtection is a list of fully qualified
27+ // domain names for which all their subdomains are exempt from
28+ // rebinding protection.
29+ ParentsExemptFromRebindingProtection []string
2530}
2631
2732func (s * Settings ) SetDefaults () {}
@@ -41,6 +46,11 @@ func (s Settings) Validate() (err error) {
4146 return fmt .Errorf ("FQDNs exempt from rebinding protection: %w" , err )
4247 }
4348
49+ err = validate .AllMatchRegex (s .ParentsExemptFromRebindingProtection , fqdnHostRegex )
50+ if err != nil {
51+ return fmt .Errorf ("parent FQDNs exempt from rebinding protection: %w" , err )
52+ }
53+
4454 return nil
4555}
4656
@@ -54,19 +64,27 @@ func (s *Settings) BlockHostnames(hostnames []string) {
5464}
5565
5666// SetRebindingProtectionExempt transforms the slice of hostnames given to
57- // FQDNs and sets these to the settings.
67+ // FQDNs and sets these to the settings. Parent domains can be exempt by
68+ // specifying the "*." prefix to the hostname, for example "*.example.com"
69+ // will exempt all subdomains of example.com from rebinding protection.
70+ // Note the wildcard cannot be used anywhere else otherwise.
5871func (s * Settings ) SetRebindingProtectionExempt (hostnames []string ) {
59- s .FqdnExemptFromRebindingProtection = make ([]string , len (hostnames ))
60- for i := range hostnames {
61- s .FqdnExemptFromRebindingProtection [i ] = dns .Fqdn (hostnames [i ])
72+ s .FqdnExemptFromRebindingProtection = make ([]string , 0 , len (hostnames ))
73+ for _ , hostname := range hostnames {
74+ if strings .HasPrefix (hostname , "*." ) {
75+ parent := hostname [2 :]
76+ s .ParentsExemptFromRebindingProtection = append (s .ParentsExemptFromRebindingProtection , dns .Fqdn (parent ))
77+ } else {
78+ s .FqdnExemptFromRebindingProtection = append (s .FqdnExemptFromRebindingProtection , dns .Fqdn (hostname ))
79+ }
6280 }
6381}
6482
6583func (s * Settings ) String () string {
6684 return s .ToLinesNode ().String ()
6785}
6886
69- func (s * Settings ) ToLinesNode () (node * gotree.Node ) {
87+ func (s * Settings ) ToLinesNode () (node * gotree.Node ) { //nolint:cyclop
7088 if len (s .IPs ) == 0 && len (s .FqdnHostnames ) == 0 &&
7189 len (s .IPPrefixes ) == 0 {
7290 return gotree .New ("Filter update: disabled" )
@@ -93,5 +111,12 @@ func (s *Settings) ToLinesNode() (node *gotree.Node) {
93111 }
94112 }
95113
114+ if len (s .ParentsExemptFromRebindingProtection ) > 0 {
115+ subNode := node .Appendf ("Parent domains exempt from rebinding protection:" )
116+ for _ , fqdn := range s .ParentsExemptFromRebindingProtection {
117+ subNode .Appendf ("%s" , fqdn )
118+ }
119+ }
120+
96121 return node
97122}
0 commit comments