1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.ipfilter;
17
18 import io.netty5.channel.Channel;
19 import io.netty5.channel.ChannelHandlerContext;
20
21 import java.net.Inet4Address;
22 import java.net.InetSocketAddress;
23 import java.net.SocketAddress;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import static java.util.Objects.requireNonNull;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class IpSubnetFilter extends AbstractRemoteAddressFilter<InetSocketAddress> {
55
56 private final boolean acceptIfNotFound;
57 private final List<IpSubnetFilterRule> ipv4Rules;
58 private final List<IpSubnetFilterRule> ipv6Rules;
59 private final IpFilterRuleType ipFilterRuleTypeIPv4;
60 private final IpFilterRuleType ipFilterRuleTypeIPv6;
61
62
63
64
65
66
67
68 public IpSubnetFilter(IpSubnetFilterRule... rules) {
69 this(true, Arrays.asList(requireNonNull(rules, "rules")));
70 }
71
72
73
74
75
76
77
78
79 public IpSubnetFilter(boolean acceptIfNotFound, IpSubnetFilterRule... rules) {
80 this(acceptIfNotFound, Arrays.asList(requireNonNull(rules, "rules")));
81 }
82
83
84
85
86
87
88
89 public IpSubnetFilter(List<IpSubnetFilterRule> rules) {
90 this(true, rules);
91 }
92
93
94
95
96
97
98
99
100 public IpSubnetFilter(boolean acceptIfNotFound, List<IpSubnetFilterRule> rules) {
101 requireNonNull(rules, "rules");
102 this.acceptIfNotFound = acceptIfNotFound;
103
104 int numAcceptIPv4 = 0;
105 int numRejectIPv4 = 0;
106 int numAcceptIPv6 = 0;
107 int numRejectIPv6 = 0;
108
109 List<IpSubnetFilterRule> unsortedIPv4Rules = new ArrayList<>();
110 List<IpSubnetFilterRule> unsortedIPv6Rules = new ArrayList<>();
111
112
113 for (IpSubnetFilterRule ipSubnetFilterRule : rules) {
114 requireNonNull(ipSubnetFilterRule, "rule");
115
116 if (ipSubnetFilterRule.getFilterRule() instanceof IpSubnetFilterRule.Ip4SubnetFilterRule) {
117 unsortedIPv4Rules.add(ipSubnetFilterRule);
118
119 if (ipSubnetFilterRule.ruleType() == IpFilterRuleType.ACCEPT) {
120 numAcceptIPv4++;
121 } else {
122 numRejectIPv4++;
123 }
124 } else {
125 unsortedIPv6Rules.add(ipSubnetFilterRule);
126
127 if (ipSubnetFilterRule.ruleType() == IpFilterRuleType.ACCEPT) {
128 numAcceptIPv6++;
129 } else {
130 numRejectIPv6++;
131 }
132 }
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 if (numAcceptIPv4 == 0 && numRejectIPv4 > 0) {
147 ipFilterRuleTypeIPv4 = IpFilterRuleType.REJECT;
148 } else if (numAcceptIPv4 > 0 && numRejectIPv4 == 0) {
149 ipFilterRuleTypeIPv4 = IpFilterRuleType.ACCEPT;
150 } else {
151 ipFilterRuleTypeIPv4 = null;
152 }
153
154 if (numAcceptIPv6 == 0 && numRejectIPv6 > 0) {
155 ipFilterRuleTypeIPv6 = IpFilterRuleType.REJECT;
156 } else if (numAcceptIPv6 > 0 && numRejectIPv6 == 0) {
157 ipFilterRuleTypeIPv6 = IpFilterRuleType.ACCEPT;
158 } else {
159 ipFilterRuleTypeIPv6 = null;
160 }
161
162 this.ipv4Rules = sortAndFilter(unsortedIPv4Rules);
163 this.ipv6Rules = sortAndFilter(unsortedIPv6Rules);
164 }
165
166 @Override
167 public boolean isSharable() {
168 return true;
169 }
170
171 @Override
172 protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) {
173 if (remoteAddress.getAddress() instanceof Inet4Address) {
174 int indexOf = Collections.binarySearch(ipv4Rules, remoteAddress, IpSubnetFilterRuleComparator.INSTANCE);
175 if (indexOf >= 0) {
176 if (ipFilterRuleTypeIPv4 == null) {
177 return ipv4Rules.get(indexOf).ruleType() == IpFilterRuleType.ACCEPT;
178 } else {
179 return ipFilterRuleTypeIPv4 == IpFilterRuleType.ACCEPT;
180 }
181 }
182 } else {
183 int indexOf = Collections.binarySearch(ipv6Rules, remoteAddress, IpSubnetFilterRuleComparator.INSTANCE);
184 if (indexOf >= 0) {
185 if (ipFilterRuleTypeIPv6 == null) {
186 return ipv6Rules.get(indexOf).ruleType() == IpFilterRuleType.ACCEPT;
187 } else {
188 return ipFilterRuleTypeIPv6 == IpFilterRuleType.ACCEPT;
189 }
190 }
191 }
192
193 return acceptIfNotFound;
194 }
195
196
197
198
199
200
201
202
203 @SuppressWarnings("ConstantConditions")
204 private static List<IpSubnetFilterRule> sortAndFilter(List<IpSubnetFilterRule> rules) {
205 Collections.sort(rules);
206 Iterator<IpSubnetFilterRule> iterator = rules.iterator();
207 List<IpSubnetFilterRule> toKeep = new ArrayList<>();
208
209 IpSubnetFilterRule parentRule = iterator.hasNext() ? iterator.next() : null;
210 if (parentRule != null) {
211 toKeep.add(parentRule);
212 }
213
214 while (iterator.hasNext()) {
215
216
217 IpSubnetFilterRule childRule = iterator.next();
218
219
220
221 if (!parentRule.matches(new InetSocketAddress(childRule.getIpAddress(), 1))) {
222 toKeep.add(childRule);
223
224 parentRule = childRule;
225 }
226 }
227
228 return toKeep;
229 }
230 }