1package multiaddr 2 3import ( 4 "net" 5 "sync" 6) 7 8// Action is an enum modelling all possible filter actions. 9type Action int32 10 11const ( 12 ActionNone Action = iota // zero value. 13 ActionAccept 14 ActionDeny 15) 16 17type filterEntry struct { 18 f net.IPNet 19 action Action 20} 21 22// Filters is a structure representing a collection of accept/deny 23// net.IPNet filters, together with the DefaultAction flag, which 24// represents the default filter policy. 25// 26// Note that the last policy added to the Filters is authoritative. 27type Filters struct { 28 DefaultAction Action 29 30 mu sync.RWMutex 31 filters []*filterEntry 32} 33 34// NewFilters constructs and returns a new set of net.IPNet filters. 35// By default, the new filter accepts all addresses. 36func NewFilters() *Filters { 37 return &Filters{ 38 DefaultAction: ActionAccept, 39 filters: make([]*filterEntry, 0), 40 } 41} 42 43func (fs *Filters) find(ipnet net.IPNet) (int, *filterEntry) { 44 s := ipnet.String() 45 for idx, ft := range fs.filters { 46 if ft.f.String() == s { 47 return idx, ft 48 } 49 } 50 return -1, nil 51} 52 53// AddDialFilter adds a deny rule to this Filters set. Hosts 54// matching the given net.IPNet filter will be denied, unless 55// another rule is added which states that they should be accepted. 56// 57// No effort is made to prevent duplication of filters, or to simplify 58// the filters list. 59// 60// Deprecated: Use AddFilter(). 61func (fs *Filters) AddDialFilter(f *net.IPNet) { 62 fs.AddFilter(*f, ActionDeny) 63} 64 65// AddFilter adds a rule to the Filters set, enforcing the desired action for 66// the provided IPNet mask. 67func (fs *Filters) AddFilter(ipnet net.IPNet, action Action) { 68 fs.mu.Lock() 69 defer fs.mu.Unlock() 70 71 if _, f := fs.find(ipnet); f != nil { 72 f.action = action 73 } else { 74 fs.filters = append(fs.filters, &filterEntry{ipnet, action}) 75 } 76} 77 78// RemoveLiteral removes the first filter associated with the supplied IPNet, 79// returning whether something was removed or not. It makes no distinction 80// between whether the rule is an accept or a deny. 81// 82// Deprecated: use RemoveLiteral() instead. 83func (fs *Filters) Remove(ipnet *net.IPNet) (removed bool) { 84 return fs.RemoveLiteral(*ipnet) 85} 86 87// RemoveLiteral removes the first filter associated with the supplied IPNet, 88// returning whether something was removed or not. It makes no distinction 89// between whether the rule is an accept or a deny. 90func (fs *Filters) RemoveLiteral(ipnet net.IPNet) (removed bool) { 91 fs.mu.Lock() 92 defer fs.mu.Unlock() 93 94 if idx, _ := fs.find(ipnet); idx != -1 { 95 fs.filters = append(fs.filters[:idx], fs.filters[idx+1:]...) 96 return true 97 } 98 return false 99} 100 101// AddrBlocked parses a ma.Multiaddr and, if a valid netip is found, it applies the 102// Filter set rules, returning true if the given address should be denied, and false if 103// the given address is accepted. 104// 105// If a parsing error occurs, or no filter matches, the Filters' 106// default is returned. 107// 108// TODO: currently, the last filter to match wins always, but it shouldn't be that way. 109// Instead, the highest-specific last filter should win; that way more specific filters 110// override more general ones. 111func (fs *Filters) AddrBlocked(a Multiaddr) (deny bool) { 112 var ( 113 netip net.IP 114 found bool 115 ) 116 117 ForEach(a, func(c Component) bool { 118 switch c.Protocol().Code { 119 case P_IP6ZONE: 120 return true 121 case P_IP6, P_IP4: 122 found = true 123 netip = net.IP(c.RawValue()) 124 return false 125 default: 126 return false 127 } 128 }) 129 130 if !found { 131 return fs.DefaultAction == ActionDeny 132 } 133 134 fs.mu.RLock() 135 defer fs.mu.RUnlock() 136 137 action := fs.DefaultAction 138 for _, ft := range fs.filters { 139 if ft.f.Contains(netip) { 140 action = ft.action 141 } 142 } 143 144 return action == ActionDeny 145} 146 147// Filters returns the list of DENY net.IPNet masks. For backwards compatibility. 148// 149// A copy of the filters is made prior to returning, so the inner state is not exposed. 150// 151// Deprecated: Use FiltersForAction(). 152func (fs *Filters) Filters() (result []*net.IPNet) { 153 ffa := fs.FiltersForAction(ActionDeny) 154 for _, res := range ffa { 155 res := res // allocate a new copy 156 result = append(result, &res) 157 } 158 return result 159} 160 161func (fs *Filters) ActionForFilter(ipnet net.IPNet) (action Action, ok bool) { 162 if _, f := fs.find(ipnet); f != nil { 163 return f.action, true 164 } 165 return ActionNone, false 166} 167 168// FiltersForAction returns the filters associated with the indicated action. 169func (fs *Filters) FiltersForAction(action Action) (result []net.IPNet) { 170 fs.mu.RLock() 171 defer fs.mu.RUnlock() 172 173 for _, ff := range fs.filters { 174 if ff.action == action { 175 result = append(result, ff.f) 176 } 177 } 178 return result 179} 180