Webconverger / webc

Webconverger's curated chroot from which updates originate
https://webconverger.org/upgrade/
73 stars 37 forks source link

Cleanup/improvement of iptables rules #70

Closed Apachez- closed 12 years ago

Apachez- commented 12 years ago

According to https://github.com/Webconverger/Debian-Live-config/blob/master/webconverger/config/includes.chroot/etc/iptables.conf the current iptables rules are:

#!/usr/bin/env iptables-restore
*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m udp -p udp --dport 631 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
COMMIT

I would like to suggest a cleanup/improvement so it will look like:

#!/usr/bin/env iptables-restore
*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Block invalid (according to conntrack) packets.
-A INPUT -m state --state INVALID -j DROP
# Block invalid and bad ICMP.
-A INPUT -p icmp --fragment -j DROP
# Allow keep state.
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Allow localhost (so Webconverger can speak to itself).
-A INPUT -i lo -j ACCEPT
# Allow and throttle incoming ping (ICMP Echo-Request).
-A INPUT -p icmp --icmp-type echo-request -m state --state NEW -m limit --limit 2/s --limit-burst 5 -j ACCEPT
COMMIT

The above could also include various methods of logging but Im not sure if this is benefitial in Webconverger case.

As debugging one could use "iptables -L -v -n" (or "iptables -L -v -n -t nat") to look at counters for which rule gets a hit (since iptables is top-down first-match in its execution) unless one wants to manually include logging rules aswell.

Apachez- commented 12 years ago

Similar rules should be applied for ip6tables aswell when IPv6 support is confirmed:

https://github.com/Webconverger/webc/issues/72

kaihendry commented 12 years ago

I like your proposal in the sense, that we drop the 631 line. However that's yet to be tested.

I don't like that there are now two lines to regulate pings.

I also don't like the fact that "invalid (according to conntrack) packets", need to explicitly dropped. Why are invalid packets accepted in the first place?

Apachez- commented 12 years ago

1) Of course it has to be tested/verified that the UDP631 line is safe to remove. But to my knowledge when you print there is an OUTbound connection (from webconverger) who is made towards the printer and not INbound (to webconverger).

2) That is so the webconverger machine isnt being used as a ping relay (or limit the effect when its being used as one). For example if someone spoofs the srcip and send an echo-request towards the webconverger box the wenconverger will send an echo-reply back to the faked srcip. Its not uncommon that the faked srcip is the true vicitim (who will receive plenty of incoming icmp packets).

By adding a throttle to how many echo-requests webconverger will accept the effect of trying to use a webconverger box as a ping relay will be limited (but also that the resources of the webconverger box itself wont be exhausted).

3) Look at net/netfilter/nf_conntrack_proto_tcp.c:

752 /* table of valid flag combinations - PUSH, ECE and CWR are always valid */
753 static const u8 tcp_valid_flags[(TCPHDR_FIN|TCPHDR_SYN|TCPHDR_RST|TCPHDR_ACK|
754                                  TCPHDR_URG) + 1] =
755 {
756         [TCPHDR_SYN]                            = 1,
757         [TCPHDR_SYN|TCPHDR_URG]                 = 1,
758         [TCPHDR_SYN|TCPHDR_ACK]                 = 1,
759         [TCPHDR_RST]                            = 1,
760         [TCPHDR_RST|TCPHDR_ACK]                 = 1,
761         [TCPHDR_FIN|TCPHDR_ACK]                 = 1,
762         [TCPHDR_FIN|TCPHDR_ACK|TCPHDR_URG]      = 1,
763         [TCPHDR_ACK]                            = 1,
764         [TCPHDR_ACK|TCPHDR_URG]                 = 1,
765 };
766
767 /* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
768 static int tcp_error(struct net *net, struct nf_conn *tmpl,
769                      struct sk_buff *skb,
770                      unsigned int dataoff,
771                      enum ip_conntrack_info *ctinfo,
772                      u_int8_t pf,
773                      unsigned int hooknum)
774 {
775         const struct tcphdr *th;
776         struct tcphdr _tcph;
777         unsigned int tcplen = skb->len - dataoff;
778         u_int8_t tcpflags;
779
780         /* Smaller that minimal TCP header? */
781         th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
782         if (th == NULL) {
783                 if (LOG_INVALID(net, IPPROTO_TCP))
784                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
785                                 "nf_ct_tcp: short packet ");
786                 return -NF_ACCEPT;
787         }
788
789         /* Not whole TCP header or malformed packet */
790         if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
791                 if (LOG_INVALID(net, IPPROTO_TCP))
792                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
793                                 "nf_ct_tcp: truncated/malformed packet ");
794                 return -NF_ACCEPT;
795         }
796
797         /* Checksum invalid? Ignore.
798          * We skip checking packets on the outgoing path
799          * because the checksum is assumed to be correct.
800          */
801         /* FIXME: Source route IP option packets --RR */
802         if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
803             nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
804                 if (LOG_INVALID(net, IPPROTO_TCP))
805                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
806                                   "nf_ct_tcp: bad TCP checksum ");
807                 return -NF_ACCEPT;
808         }
809
810         /* Check TCP flags. */
811         tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH));
812         if (!tcp_valid_flags[tcpflags]) {
813                 if (LOG_INVALID(net, IPPROTO_TCP))
814                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
815                                   "nf_ct_tcp: invalid TCP flag combination ");
816                 return -NF_ACCEPT;
817         }
818
819         return NF_ACCEPT;
820 }

Droping invalid packets means that we will throw away packets who has a combination of tcp-flags which just isnt valid.

This can be done manually in iptables if one use Linux kernel older than v2.6.9:

iptables -N BADTCP_DROP
iptables -A BADTCP_DROP -m limit --limit 2/s --limit-burst 5 -j LOG --log-tcp-options --log-ip-options --log-level 7 --log-prefix "f=BADTCP a=DROP "
iptables -A BADTCP_DROP -j DROP

iptables -N BADTCP
iptables -A BADTCP -p tcp --tcp-flags PSH PSH -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL ACK -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL ACK,URG -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL SYN -m state --state NEW -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL SYN,ACK -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL FIN,ACK -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL FIN,ACK,URG -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL RST -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -p tcp --tcp-flags ALL RST,ACK -m state --state ESTABLISHED -j RETURN
iptables -A BADTCP -j BADTCP_DROP

iptables -A INPUT -i ${OUTSIDE_DEVICE} -p tcp -j BADTCP
iptables -A FORWARD -i ${OUTSIDE_DEVICE} -p tcp -j BADTCP
Apachez- commented 12 years ago

I have added two rules:

When the webconverger will use PMTU (enabled by default in linux kernel) we must allow incoming ICMP type destination-unreachable code fragmentation-needed for it to fully function. See http://en.wikipedia.org/wiki/Path_MTU_Discovery for more information.

Source Quench is one (of several) methods to inform the sender to send at a slower rate (for example if buffers are being exhausted on a router or host). See http://en.wikipedia.org/wiki/ICMP_Source_Quench for more information.

#!/usr/bin/env iptables-restore
*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Block invalid (according to conntrack) packets.
-A INPUT -m state --state INVALID -j DROP
# Block fragmented ICMP.
-A INPUT -p icmp --fragment -j DROP
# Allow keep state.
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Allow localhost (so Webconverger can speak to itself).
-A INPUT -i lo -j ACCEPT
# Allow incoming Path MTU Discovery (ICMP destination-unreachable/fragmentation-needed)
-A INPUT -p icmp --icmp-type 3/4 -m state --state NEW -j ACCEPT
# Allow incoming request to decrease rate of sent packets (ICMP Source Quench)
-A INPUT -p icmp --icmp-type 4 -m state --state NEW -j ACCEPT
# Allow and throttle incoming ping (ICMP Echo-Request).
-A INPUT -p icmp --icmp-type 8 -m state --state NEW -m limit --limit 2/s --limit-burst 5 -j ACCEPT
COMMIT
kaihendry commented 12 years ago

I will drop in your suggestions once I can confirm printer detection happens before and after these changes :) https://github.com/Webconverger/webc/issues/46

Do you have a printer queue at work you can try the latest upon http://build.webconverger.org/ ?