1 |
On 12/27/2012 10:59 PM, Walter Dnes wrote: |
2 |
> |
3 |
> Here's my revised "Paranoia Plus" ruleset. Any comments? Because I'm |
4 |
> behind a NAT-ing ADSL router/modem, many of my rules rarely see hits. |
5 |
> However, I do have a backup dialup connection in case of problems, so |
6 |
> most of my rules don't specify the network interface. A couple of |
7 |
> notes... |
8 |
> |
9 |
|
10 |
I did a bunch of inline comments below as I was trying to understand the |
11 |
rules. At the end I give the tl;dr, but maybe the inline comments are |
12 |
useful too. |
13 |
|
14 |
|
15 |
> * My little lan is 192.168.123.248/29 |
16 |
> * I have a TV tuner box that comes up in the zero-config space, so I |
17 |
> have to allow 169.254.0.0/16 |
18 |
> * I "dislike" a certain button following me. |
19 |
> |
20 |
> # Generated by iptables-save v1.4.16.3 on Thu Dec 27 22:43:12 2012 |
21 |
> *filter |
22 |
> :INPUT DROP [0:0] |
23 |
> :FORWARD DROP [0:0] |
24 |
> :OUTPUT DROP [0:0] |
25 |
|
26 |
You can save yourself some complexity by allowing outbound traffic by |
27 |
default. I see that your INPUT policy is set to DROP, but you override |
28 |
this in a few places: at the end of all the chains, you jump to the |
29 |
PRIVATE table, which ends with a -j ACCEPT. So you'll accept anything |
30 |
that isn't rejected by a previous rule. |
31 |
|
32 |
I'd suggesting flipping that: get rid of the -j ACCEPT at the end of the |
33 |
private table, and allow unmatched traffic to be dropped. |
34 |
|
35 |
|
36 |
|
37 |
> :DROP_LOG - [0:0] |
38 |
> :FECESBOOK - [0:0] |
39 |
> :ICMP_IN - [0:0] |
40 |
> :PRIVATE - [0:0] |
41 |
> :PRIVATE_LOG - [0:0] |
42 |
> :TCP_IN - [0:0] |
43 |
> :UDP_IN - [0:0] |
44 |
> :UNSOLICITED - [0:0] |
45 |
|
46 |
> [0:0] -A INPUT -s 192.168.123.248/29 -i eth0 -j ACCEPT |
47 |
|
48 |
Since you've self-proclaimed as paranoid, I don't feel bad suggesting |
49 |
that you choose which ports to allow incoming, even to the LAN. If |
50 |
somebody brings (or creates!) a compromised machine onto your LAN, |
51 |
they're going to be able to hit any ports that you've got open and |
52 |
available through the firewall. Not much you can do about that. |
53 |
|
54 |
But you might as well prevent them from reaching everything. If you |
55 |
expect to SSH from the LAN, sure, let that in. But if you're not serving |
56 |
e.g. web pages, you might as well block port 80 from the LAN. This |
57 |
allows you the freedom to play with apache without worrying about |
58 |
whether or not you've secured it. |
59 |
|
60 |
|
61 |
> [0:0] -A INPUT -s 169.254.0.0/16 -i eth0 -j ACCEPT |
62 |
|
63 |
I don't know anything about zeroconf, not qualified to comment. |
64 |
|
65 |
|
66 |
> [0:0] -A INPUT -s 69.63.176.0/20 -j FECESBOOK |
67 |
> [0:0] -A INPUT -s 69.220.144.0/20 -j FECESBOOK |
68 |
> [0:0] -A INPUT -s 69.63.176.0/20 -j FECESBOOK |
69 |
> [0:0] -A INPUT -s 69.171.224.0/19 -j FECESBOOK |
70 |
> [0:0] -A INPUT -s 200.58.112.0/20 -j FECESBOOK |
71 |
> [0:0] -A INPUT -s 213.155.64.0/19 -j FECESBOOK |
72 |
> [0:0] -A FECESBOOK -j LOG --log-prefix "FECESBOOK:" --log-level 6 |
73 |
> [0:0] -A FECESBOOK -j DROP |
74 |
|
75 |
Cute =) That final DROP is only needed since you -j PRIVATE (which |
76 |
defaults to ACCEPT) at the end of everything. |
77 |
|
78 |
|
79 |
> [0:0] -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT |
80 |
> [0:0] -A INPUT -p udp -m udp --sport 53 -j ACCEPT |
81 |
|
82 |
Ok, in the INPUT chain you're accepting DNS traffic early. You do it |
83 |
again below, so I think the later one is redundant. |
84 |
|
85 |
|
86 |
> [0:0] -A INPUT -i lo -j ACCEPT |
87 |
> [0:0] -A INPUT -f -j LOG --log-prefix "FRAGMENTS:" --log-level 6 |
88 |
> [0:0] -A INPUT -f -j DROP |
89 |
> [0:0] -A INPUT -p tcp -j TCP_IN |
90 |
> [0:0] -A INPUT -p udp -j UDP_IN |
91 |
> [0:0] -A INPUT -p icmp -j ICMP_IN |
92 |
> [0:0] -A INPUT -j LOG --log-prefix "BAD_PROTOCOL:" --log-level 6 |
93 |
> [0:0] -A INPUT -j DROP |
94 |
|
95 |
DROP is redundant, since the INPUT policy is DROP. |
96 |
|
97 |
|
98 |
> [0:0] -A OUTPUT -d 192.168.123.248/29 -o eth0 -j ACCEPT |
99 |
> [0:0] -A OUTPUT -o lo -j ACCEPT |
100 |
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT |
101 |
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT |
102 |
> [0:0] -A OUTPUT -p icmp -m icmp --icmp-type 30 -j ACCEPT |
103 |
> [0:0] -A OUTPUT -p tcp -m tcp --sport 0:1023 -j DROP_LOG |
104 |
> [0:0] -A OUTPUT -p udp -m udp --sport 0:1023 -j DROP_LOG |
105 |
> [0:0] -A OUTPUT -p tcp -m tcp --sport 6000:6063 -j DROP_LOG |
106 |
> [0:0] -A OUTPUT -p udp -m udp --sport 6000:6063 -j DROP_LOG |
107 |
> [0:0] -A OUTPUT -j ACCEPT |
108 |
|
109 |
Aha, you're overriding the OUTPUT policy of DROP here with an ACCEPT. |
110 |
You might as well set the policy to ACCEPT, and get rid of the trailing |
111 |
-j ACCEPT. Anything that is explicitly ACCEPTed above but not otherwise |
112 |
DROPped is also redundant, since traffic will be accepted by default if |
113 |
not dropped. I see that you want to log-before-drop specific traffic; |
114 |
that would still work with a policy of ACCEPT. You would add only those |
115 |
rules to the OUTPUT chain. |
116 |
|
117 |
|
118 |
> [0:0] -A DROP_LOG -j LOG --log-level 6 |
119 |
> [0:0] -A DROP_LOG -j DROP |
120 |
|
121 |
DROP would be redundant without the -j ACCEPT at the end of the PRIVATE |
122 |
TABLE. |
123 |
|
124 |
|
125 |
> [0:0] -A ICMP_IN -p icmp -m conntrack --ctstate NEW -j UNSOLICITED |
126 |
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 0 -j PRIVATE |
127 |
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 3 -j PRIVATE |
128 |
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 4 -j PRIVATE |
129 |
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 11 -j PRIVATE |
130 |
> [0:0] -A ICMP_IN -p icmp -m icmp --icmp-type 12 -j PRIVATE |
131 |
> [0:0] -A ICMP_IN -j LOG --log-prefix "IN_BAD_ICMP:" --log-level 6 |
132 |
> [0:0] -A ICMP_IN -j DROP |
133 |
|
134 |
DROP would be redundant without the -j ACCEPT at the end of the PRIVATE |
135 |
TABLE. |
136 |
|
137 |
|
138 |
> [0:0] -A PRIVATE -s 10.0.0.0/8 -j PRIVATE_LOG |
139 |
> [0:0] -A PRIVATE -s 127.0.0.0/8 -j PRIVATE_LOG |
140 |
> [0:0] -A PRIVATE -s 172.16.0.0/12 -j PRIVATE_LOG |
141 |
> [0:0] -A PRIVATE -s 192.168.0.0/16 -j PRIVATE_LOG |
142 |
> [0:0] -A PRIVATE -j ACCEPT |
143 |
|
144 |
This is where you essentially set an ACCEPT policy, since all unmatched |
145 |
traffic winds up here. |
146 |
|
147 |
|
148 |
> [0:0] -A PRIVATE_LOG -j LOG --log-prefix "IN_BAD_ADDR:" --log-level 6 |
149 |
> [0:0] -A PRIVATE_LOG -j DROP |
150 |
|
151 |
DROP would be redundant without the -j ACCEPT at the end of the PRIVATE |
152 |
TABLE. |
153 |
|
154 |
|
155 |
> [0:0] -A TCP_IN -p tcp -m tcp --dport 0:1023 -j DROP_LOG |
156 |
> [0:0] -A TCP_IN -p tcp -m tcp --dport 6000:6063 -j DROP_LOG |
157 |
> [0:0] -A TCP_IN -p tcp -m tcp --sport 53 -j PRIVATE |
158 |
|
159 |
I think you already accepted the DNS traffic. |
160 |
|
161 |
|
162 |
> [0:0] -A TCP_IN -p tcp -m tcp --sport 80 -j PRIVATE |
163 |
> [0:0] -A TCP_IN -p tcp -m conntrack --ctstate NEW -m tcp -j UNSOLICITED |
164 |
> [0:0] -A TCP_IN -p tcp -j PRIVATE |
165 |
|
166 |
By jumping to the PRIVATE table at the end, you've basically set a |
167 |
policy of ACCEPT, since the PRIVATE chain ends with a -j ACCEPT. |
168 |
|
169 |
|
170 |
> [0:0] -A UDP_IN -p udp -m udp --dport 0:1023 -j DROP_LOG |
171 |
> [0:0] -A UDP_IN -p udp -m udp --dport 6000:6063 -j DROP_LOG |
172 |
> [0:0] -A UDP_IN -p udp -m udp --sport 53 -j PRIVATE |
173 |
|
174 |
DNS, probably already accepted this. |
175 |
|
176 |
|
177 |
> [0:0] -A UDP_IN -p udp -m udp --sport 80 -j PRIVATE |
178 |
> [0:0] -A UDP_IN -p udp -m conntrack --ctstate NEW -j UNSOLICITED |
179 |
> [0:0] -A UDP_IN -p udp -j PRIVATE |
180 |
|
181 |
Same as at the end of TCP_IN. By jumping to the PRIVATE table at the |
182 |
end, you've basically set a policy of ACCEPT for anything tcp, udp, or icmp. |
183 |
|
184 |
|
185 |
> [0:0] -A UNSOLICITED -j LOG --log-prefix "UNSOLICITED:" --log-level 6 |
186 |
> [0:0] -A UNSOLICITED -j DROP |
187 |
|
188 |
DROP would be redundant without the -j ACCEPT at the end of the PRIVATE |
189 |
TABLE. |
190 |
|
191 |
|
192 |
In the TCP_IN and UDP_IN tables, you try to reject NEW connections |
193 |
before passing onto the PRIVATE chain which eventually allows the |
194 |
traffic. So you kind-of have an ACCEPT policy, but you want to reject |
195 |
any traffic that isn't for an established connection. This can be |
196 |
simplified by switching to a default-DROP policy, and allowing |
197 |
RELATED,ESTABLISHED connections through instead. |
198 |
|
199 |
Here's an example that will almost certainly need some work (I haven't |
200 |
even tried to run it). |
201 |
|
202 |
# Flush existing rules |
203 |
iptables -F |
204 |
|
205 |
# Delete user-defined chains. |
206 |
iptables -X FECESBOOK |
207 |
iptables -X DROP_LOG |
208 |
iptables -X TCP_IN |
209 |
iptables -X UDP_IN |
210 |
iptables -X ICMP_IN |
211 |
|
212 |
# Recreate (empty) user-defined chains. |
213 |
iptables -N FECESBOOK |
214 |
iptables -N DROP_LOG |
215 |
iptables -N TCP_IN |
216 |
iptables -N UDP_IN |
217 |
iptables -N ICMP_IN |
218 |
|
219 |
# Set policies |
220 |
iptables -P INPUT DROP |
221 |
iptables -P FORWARD DROP |
222 |
iptables -P OUTPUT ACCEPT |
223 |
|
224 |
# |
225 |
# Add FECESBOOK rules |
226 |
# |
227 |
iptables -A FECESBOOK -j LOG --log-prefix "FECESBOOK:" --log-level 6 |
228 |
iptables -A FECESBOOK -j DROP |
229 |
|
230 |
# |
231 |
# Add DROP_LOG rules |
232 |
# |
233 |
iptables -A DROP_LOG -j LOG --log-level 6 |
234 |
iptables -A DROP_LOG -j DROP |
235 |
|
236 |
# |
237 |
# Add ICMP_IN rules |
238 |
# |
239 |
ALLOWED_ICMP="0 3 4 8 11 12 30" |
240 |
|
241 |
for ok_icmp in ALLOWED_ICMP; do |
242 |
iptables -A ICMP_IN -p icmp --icmp-type "${ok_icmp}" -j ACCEPT |
243 |
done |
244 |
|
245 |
iptables -A ICMP_IN -j LOG --log-prefix "IN_BAD_ICMP:" --log-level 6 |
246 |
|
247 |
# |
248 |
# Add TCP_IN rules |
249 |
# |
250 |
iptables -A TCP_IN -p tcp -m tcp --dport 0:1023 -j DROP_LOG |
251 |
iptables -A TCP_IN -p tcp -m tcp --dport 6000:6063 -j DROP_LOG |
252 |
|
253 |
# Add UDP_IN rules |
254 |
iptables -A UDP_IN -p udp -m udp --dport 0:1023 -j DROP_LOG |
255 |
iptables -A UDP_IN -p udp -m udp --dport 6000:6063 -j DROP_LOG |
256 |
|
257 |
|
258 |
# |
259 |
# Main INPUT chain |
260 |
# |
261 |
# |
262 |
# Allow your LAN/Zeroconf stuff. For more paranoia (recommended), allow |
263 |
# only specific ports. |
264 |
iptables -A OUTPUT -o lo -j ACCEPT |
265 |
iptables -A INPUT -s 192.168.123.248/29 -i eth0 -j ACCEPT |
266 |
iptables -A INPUT -s 169.254.0.0/16 -i eth0 -j ACCEPT |
267 |
|
268 |
# Block this stuff before allowing related, established traffic. |
269 |
# That is, block Facebook traffic, period. |
270 |
# A list of Facebook CIDRs. |
271 |
FECESBOOK="69.63.176.0/20 69.220.144.0/20 69.63.176.0/20 69.171.224.0/19 |
272 |
200.58.112.0/20 213.155.64.0/19" |
273 |
|
274 |
for fb in $FECESBOOK; do |
275 |
iptables -A INPUT -s "${fb} -j FECESBOOK |
276 |
done |
277 |
|
278 |
# Drop fragmented packets without further consideration. |
279 |
iptables -A INPUT -f -j LOG --log-prefix "FRAGMENTS:" --log-level 6 |
280 |
iptables -A INPUT -f -j DROP |
281 |
|
282 |
# If you initiate a connection, allow the response to come back in. |
283 |
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT |
284 |
|
285 |
# For all other (i.e. NEW) traffic, filter by protocol. |
286 |
iptables -A INPUT -p tcp -j TCP_IN |
287 |
iptables -A INPUT -p udp -j UDP_IN |
288 |
iptables -A INPUT -p icmp -j ICMP_IN |
289 |
|
290 |
# If it isn't TCP, UDP, or ICMP, we probably don't want it. |
291 |
iptables -A INPUT -j LOG --log-prefix "BAD_PROTOCOL:" --log-level 6 |
292 |
|
293 |
# |
294 |
# At this point, anything not matched is dropped. |
295 |
# |