* REJECT using invalid data @ 2004-12-07 1:01 Simon Kirby 2004-12-07 11:07 ` Pablo Neira 0 siblings, 1 reply; 10+ messages in thread From: Simon Kirby @ 2004-12-07 1:01 UTC (permalink / raw) To: netfilter-devel Hello, After some recent interesting network issues involving an onboard Tigon3 card with faulty buffer memory, we discovered that netfilter has some issues with handling corrupted packets. This took quite some time to diagnose, I might add. :) It appears that a packet with a bad TCP checksum will be disregarded by the state tracking code (and apparently shows up as "INVALID"). Fine. However, the same packet will then likely continue traversing rules until it hits some kind of REJECT rule. REJECT can be set to reject with a tcp-reset or some ICMP response at this point. If so, it will actually use the possibly-incorrect information from the bad TCP packet and send a rejection packet. As far as I can tell, this is a bug. What happens as a result of this is that any corrupted packet will result in TCP sessions being immediately terminated. This is bad because normally TCP would retransmit and recover from the error. I'm quite busy but I can look at creating a patch for this if nobody has any immediate objections (or already knows how to easily make the patch). Thanks, Simon- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 1:01 REJECT using invalid data Simon Kirby @ 2004-12-07 11:07 ` Pablo Neira 2004-12-07 17:28 ` Simon Kirby 0 siblings, 1 reply; 10+ messages in thread From: Pablo Neira @ 2004-12-07 11:07 UTC (permalink / raw) To: Simon Kirby; +Cc: netfilter-devel Simon Kirby wrote: >After some recent interesting network issues involving an onboard Tigon3 >card with faulty buffer memory, we discovered that netfilter has some >issues with handling corrupted packets. This took quite some time to >diagnose, I might add. :) > >It appears that a packet with a bad TCP checksum will be disregarded by >the state tracking code (and apparently shows up as "INVALID"). Fine. > >However, the same packet will then likely continue traversing rules until >it hits some kind of REJECT rule. > not really, my ruleset drops it, actually another rule here is previously logging it. -A INPUT -m state --state INVALID -j DROP > REJECT can be set to reject with a >tcp-reset or some ICMP response at this point. If so, it will actually >use the possibly-incorrect information from the bad TCP packet and send a >rejection packet. As far as I can tell, this is a bug. > > yes, that's a bug, but in your ruleset, people should log/drop/let continue invalid packets, but not reject them. So I don't see the point of sending a patch. Maybe you could send a patch to clarify this in the man page. -- Pablo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 11:07 ` Pablo Neira @ 2004-12-07 17:28 ` Simon Kirby 2004-12-07 22:14 ` Pablo Neira 0 siblings, 1 reply; 10+ messages in thread From: Simon Kirby @ 2004-12-07 17:28 UTC (permalink / raw) To: Pablo Neira; +Cc: netfilter-devel On Tue, Dec 07, 2004 at 12:07:15PM +0100, Pablo Neira wrote: > not really, my ruleset drops it, actually another rule here is > previously logging it. > > -A INPUT -m state --state INVALID -j DROP That's all fine and dandy, except that we can't use state tracking in our configuration because of asymmetric routing (which is required due to BGP). This is fairly common, and not an incorrect setup. > > REJECT can be set to reject with a > >tcp-reset or some ICMP response at this point. If so, it will actually > >use the possibly-incorrect information from the bad TCP packet and send a > >rejection packet. As far as I can tell, this is a bug. > > yes, that's a bug, but in your ruleset, people should log/drop/let No! It is not a bug in our ruleset, it is a bug in REJECT. It is incorrect to reply to packet layers that have bad checksums. REJECT in this case must DROP, because anything else would be broken. Simon- ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 17:28 ` Simon Kirby @ 2004-12-07 22:14 ` Pablo Neira 2004-12-08 2:47 ` Kiran Kumar Immidi 0 siblings, 1 reply; 10+ messages in thread From: Pablo Neira @ 2004-12-07 22:14 UTC (permalink / raw) To: Simon Kirby; +Cc: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 1329 bytes --] Simon Kirby wrote: >On Tue, Dec 07, 2004 at 12:07:15PM +0100, Pablo Neira wrote: > > >>not really, my ruleset drops it, actually another rule here is >>previously logging it. >> >>-A INPUT -m state --state INVALID -j DROP >> >> > >That's all fine and dandy, except that we can't use state tracking in our >configuration because of asymmetric routing (which is required due to >BGP). This is fairly common, and not an incorrect setup. > > Hm I thought that you were using state tracking... I agree your setup is correct. >>>REJECT can be set to reject with a >>>tcp-reset or some ICMP response at this point. If so, it will actually >>>use the possibly-incorrect information from the bad TCP packet and send a >>>rejection packet. As far as I can tell, this is a bug. >>> >>> >>yes, that's a bug, but in your ruleset, people should log/drop/let >> >> > >No! It is not a bug in our ruleset, it is a bug in REJECT. > >It is incorrect to reply to packet layers that have bad checksums. >REJECT in this case must DROP, because anything else would be broken. > > Now I see, if state tracking is not enable there's no way to avoid this problem. But I guess that we should drop all malformed packets, not only those which have bad checksums. Would you like to give a try to the patch attached? -- Pablo [-- Attachment #2: reject.patch --] [-- Type: text/x-patch, Size: 3030 bytes --] ===== net/ipv4/netfilter/ipt_REJECT.c 1.32 vs edited ===== --- 1.32/net/ipv4/netfilter/ipt_REJECT.c 2004-11-13 14:41:07 +01:00 +++ edited/net/ipv4/netfilter/ipt_REJECT.c 2004-12-07 23:03:29 +01:00 @@ -352,6 +352,76 @@ ip_finish_output); } +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 +#define TH_ECE 0x40 +#define TH_CWR 0x80 + +/* table of valid flag combinations - ECE and CWR are always valid */ +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = +{ + [TH_SYN] = 1, + [TH_SYN|TH_ACK] = 1, + [TH_RST] = 1, + [TH_RST|TH_ACK] = 1, + [TH_RST|TH_ACK|TH_PUSH] = 1, + [TH_FIN|TH_ACK] = 1, + [TH_ACK] = 1, + [TH_ACK|TH_PUSH] = 1, + [TH_ACK|TH_URG] = 1, + [TH_ACK|TH_URG|TH_PUSH] = 1, + [TH_FIN|TH_ACK|TH_PUSH] = 1, + [TH_FIN|TH_ACK|TH_URG] = 1, + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1, +}; + +/* Protect against broken packets. Reduced version of tcp_error, taken + * from tcp connection tracking. + * + * If someone else needs this piece of code, we should move this elsewhere + * instead of copying it over and over again --pablo + */ +static int tcp_error(struct sk_buff *skb, unsigned int hooknum) +{ + struct iphdr *iph = skb->nh.iph; + struct tcphdr _tcph, *th; + unsigned int tcplen = skb->len - iph->ihl * 4; + u_int8_t tcpflags; + + /* Smaller that minimal TCP header? */ + th = skb_header_pointer(skb, iph->ihl * 4, + sizeof(_tcph), &_tcph); + if (th == NULL) + return 1; + + /* Not whole TCP header or malformed packet */ + if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) + return 1; + + /* Checksum invalid? Ignore. + * We skip checking packets on the outgoing path + * because the semantic of CHECKSUM_HW is different there + * and moreover root might send raw packets. + */ + /* FIXME: Source route IP option packets --RR */ + if (hooknum == NF_IP_PRE_ROUTING + && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, + skb->ip_summed == CHECKSUM_HW ? skb->csum + : skb_checksum(skb, iph->ihl*4, tcplen, 0))) + return 1; + + /* Check TCP flags. */ + tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR)); + if (!tcp_valid_flags[tcpflags]) + return 1; + + return 0; +} + static unsigned int reject(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, @@ -364,6 +434,12 @@ /* Our naive response construction doesn't deal with IP options, and probably shouldn't try. */ if ((*pskb)->nh.iph->ihl<<2 != sizeof(struct iphdr)) + return NF_DROP; + + /* It is incorrect to reply to malformed packet. + * REJECT in this case must DROP, because anything + * else would be broken. */ + if (tcp_error(*pskb, hooknum)) return NF_DROP; /* WARNING: This code causes reentry within iptables. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 22:14 ` Pablo Neira @ 2004-12-08 2:47 ` Kiran Kumar Immidi 0 siblings, 0 replies; 10+ messages in thread From: Kiran Kumar Immidi @ 2004-12-08 2:47 UTC (permalink / raw) To: Pablo Neira, Simon Kirby; +Cc: netfilter-devel On Wednesday 08 December 2004 03:44, Pablo Neira wrote: >Now I see, if state tracking is not enable there's no way to avoid this >problem. But I guess that we should drop all malformed packets, not only >those which have bad checksums. Would you like to give a try to the >patch attached? Just a comment on this; +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = This makes the array about 64 bytes long, would be better to store as an array of valid flags rather than as a bit mask; -- Regards, Kiran Kumar Immidi ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <Pine.LNX.4.53.0412072347080.2736@bizon.gios.gov.pl>]
* Re: REJECT using invalid data [not found] <Pine.LNX.4.53.0412072347080.2736@bizon.gios.gov.pl> @ 2004-12-07 23:54 ` Pablo Neira 2004-12-08 0:33 ` Krzysztof Oledzki 2004-12-08 0:52 ` Simon Kirby 0 siblings, 2 replies; 10+ messages in thread From: Pablo Neira @ 2004-12-07 23:54 UTC (permalink / raw) To: Krzysztof Oledzki; +Cc: Netfilter Development Mailinglist Krzysztof Oledzki wrote: >I'm not sure if changing "-j REJECT" to drop invalid tcp packets is good >idea since we have -m unclean and we can drop such packets explicitly >with this match. > unclean was removed from 2.6 series > And what about other protocols (udp, etc) when REJECT >generates ICMP port-unreachable? > > you are right, udp stuff is missing, checkings here are trivial to add anyway. I'll think about this issue more carefully in next days. -- Pablo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 23:54 ` Pablo Neira @ 2004-12-08 0:33 ` Krzysztof Oledzki 2004-12-08 0:52 ` Simon Kirby 1 sibling, 0 replies; 10+ messages in thread From: Krzysztof Oledzki @ 2004-12-08 0:33 UTC (permalink / raw) To: Pablo Neira; +Cc: Netfilter Development Mailinglist On Wed, 8 Dec 2004, Pablo Neira wrote: > Krzysztof Oledzki wrote: > > >I'm not sure if changing "-j REJECT" to drop invalid tcp packets is good > >idea since we have -m unclean and we can drop such packets explicitly > >with this match. > > > > unclean was removed from 2.6 series Oh? I did not know about that... After some googling I have just found http://lists.netfilter.org/pipermail/netfilter-devel/2003-August/012199.html So, how it is now possible to DROP invalid packets? I think that it should be at least a match which can be used to drop broken or malformed packets such as ones used to expoloit buggy IP stack on old win95 hosts. > > And what about other protocols (udp, etc) when REJECT > >generates ICMP port-unreachable? > > > you are right, udp stuff is missing, checkings here are trivial to add > anyway. I'll think about this issue more carefully in next days. OK. Best regards, Krzysztof Olędzki ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: REJECT using invalid data 2004-12-07 23:54 ` Pablo Neira 2004-12-08 0:33 ` Krzysztof Oledzki @ 2004-12-08 0:52 ` Simon Kirby [not found] ` <Pine.LNX.4.53.0412101310210.1288@bizon.gios.gov.pl> 1 sibling, 1 reply; 10+ messages in thread From: Simon Kirby @ 2004-12-08 0:52 UTC (permalink / raw) To: Pablo Neira; +Cc: Netfilter Development Mailinglist, Krzysztof Oledzki On Wed, Dec 08, 2004 at 12:54:09AM +0100, Pablo Neira wrote: > >And what about other protocols (udp, etc) when REJECT > >generates ICMP port-unreachable? > > you are right, udp stuff is missing, checkings here are trivial to add > anyway. I'll think about this issue more carefully in next days. I don't think it's a good idea to try to filter all TCP flags in REJECT unless we're trying to avoid rejecting rejects and we don't already do that for some reason (eep), for the same reason that unclean was removed (ECN and other new functionality could break). I would think that all that is needed is a check for the RST bit. At the same time, it would be nice to have a match (or at least some functionality) resulting in the ability to drop corrupted packets ("corrupted" as in with the checksum) that would otherwise be accepted. Hmm. Maybe this should be done at a different level? It should basically not match "-p tcp" in the rule "iptables -p tcp -j REJECT". Doing it at "-p tcp" time would also correct "iptables -p tcp --dport 80 -j ACCEPT", which would otherwise also be affected by the same problem (the TCP port could be corrupted). Simon- ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <Pine.LNX.4.53.0412101310210.1288@bizon.gios.gov.pl>]
* Re: REJECT using invalid data [not found] ` <Pine.LNX.4.53.0412101310210.1288@bizon.gios.gov.pl> @ 2004-12-10 13:10 ` Simon Kirby [not found] ` <Pine.LNX.4.53.0412101439530.6072@bizon.gios.gov.pl> 0 siblings, 1 reply; 10+ messages in thread From: Simon Kirby @ 2004-12-10 13:10 UTC (permalink / raw) To: Krzysztof Oledzki; +Cc: Netfilter Development Mailinglist, Pablo Neira On Fri, Dec 10, 2004 at 01:29:30PM +0100, Krzysztof Oledzki wrote: > > I don't think it's a good idea to try to filter all TCP flags in REJECT > > unless we're trying to avoid rejecting rejects and we don't already do > > that for some reason (eep), for the same reason that unclean was removed > > (ECN and other new functionality could break). I would think that all > > that is needed is a check for the RST bit. > > > > At the same time, it would be nice to have a match (or at least some > > functionality) resulting in the ability to drop corrupted packets > > ("corrupted" as in with the checksum) that would otherwise be accepted. > > > > Hmm. Maybe this should be done at a different level? It should > > basically not match "-p tcp" in the rule "iptables -p tcp -j REJECT". > > Doing it at "-p tcp" time would also correct "iptables -p tcp --dport 80 > > -j ACCEPT", which would otherwise also be affected by the same problem > > (the TCP port could be corrupted). > > No. We simply can't do that. Please consider such config: > iptables -A INPUT -p tcp -j ACCEPT > iptables -A INPUT -j REJECT Yes, what's the problem? If the TCP checksum is fine, "-p tcp" will match and it will accept the packet. If it is corrupted, "-p tcp" will not match and the ACCEPT rule will not match. The REJECT rule will then DROP the packet. There is nothing wrong with this. The only difference here is the use of "-p tcp" alone to literally match the protocol in the IP header (under the IP checksum) versus the use of "-p tcp" to enable inspection of the TCP header. For example, if this rule were to match a packet with a bad TCP checksum, it would be broken (because the port could be corrupted): iptables -A INPUT -p tcp --dport 80 -j ACCEPT On the other hand, it would not be broken to match in this case: iptables -A INPUT -p tcp -j ACCEPT ...which may be what you are getting at. Fixing this requires a syntax or design change, most likely. > I thing we really need somethig like "-m malformed" so we can do tricks > like: iptables -A FORWARD -m malformed -j DROP (to drop malformed packets) > or: iptables -A FORWARD -m malformed -j ACCEPT (to stop further processing such packets) Sure, adding the a corrupted test is useful for things such as logging, etc. However, requiring the firewall user to check for corruption explicitly before any "-p tcp --tcp-blah" rules is just going to make the iptables learning curve even higher, and 99% of us are going to miss it. Simply, I think it's broken. So, how does the code structure of iptables work in this case? Can the checksum be added in a single place such that "-p tcp" alone will match but any of --dport, --sport, --syn, --tcp-flags, --tcp-option, --mss, multiport, etc? Simon- ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <Pine.LNX.4.53.0412101439530.6072@bizon.gios.gov.pl>]
* Re: REJECT using invalid data [not found] ` <Pine.LNX.4.53.0412101439530.6072@bizon.gios.gov.pl> @ 2004-12-10 14:49 ` Simon Kirby 0 siblings, 0 replies; 10+ messages in thread From: Simon Kirby @ 2004-12-10 14:49 UTC (permalink / raw) To: Krzysztof Oledzki; +Cc: Netfilter Development Mailinglist, Pablo Neira On Fri, Dec 10, 2004 at 02:52:29PM +0100, Krzysztof Oledzki wrote: > No, REJECT does not DROP. It sends back an error packet in response. So it > sends response to broken packets. Yes, but if REJECT can't REJECT it, it very well better DROP instead. Would you rather it ACCEPT it? > Oh, but what if protocol filed is broken? With one bit error we can > accidently match for example igmp packets with -p tcp. "tcp", "udp", "igmp", etc., are in the IP header, which better be checked by that point as well. That is what I'm saying in my previous message. "-p tcp" by itself is matching in only the IP header, which has a separate checksum. > Not only for logging. You can use this to protect some hosts with > broken IP stack like for example unpatched Win95/98, etc. I'm not against a feature to actually match broken packets in any way. I'm just saying that not checking the checksum and skipping such packets with the rule "-p tcp --dport 80" is wrong. > So maybe broken packets should go a to different table (broken) and not > traversal other tables and conntrack? Or any other smart solution. Possibly. The kernel would need to know all protocols in order to be able to filter them before any other rules, though. Let me make this very clear. I am talking only about the bad checksum case, and not about strange or "unclean" packets in any other way. Would you ever really ever want to accept a packet with a corrupted checksum? Would it ever be useful? Ideally, "-p tcp" could check just the checksums up to the IP level and NOT the tcp checksum. "-p tcp" with any other TCP-specific option would then check the TCP checksum. So, we could have an example ruleset like this that should work as expected: iptables -A FORWARD -d windows_box -m broken --broken-win -J DROP iptables -A FORWARD -m unclean --some-unclean -m limit ... -J LOG iptables -A FORWARD -p tcp --dport 80 -J ACCEPT iptables -A FORWARD -p tcp -j REJECT --reject-with tcp-reset The above rules would protect the Windows box, log corrupted packets, accept TCP port 80 packets that don't have a corrupted TCP checksum, REJECT any other valid TCP packet with a TCP RST, DROP invalid TCP packets, and follow the policy for the rest. Simple. Simon- ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2004-12-10 14:49 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-07 1:01 REJECT using invalid data Simon Kirby
2004-12-07 11:07 ` Pablo Neira
2004-12-07 17:28 ` Simon Kirby
2004-12-07 22:14 ` Pablo Neira
2004-12-08 2:47 ` Kiran Kumar Immidi
[not found] <Pine.LNX.4.53.0412072347080.2736@bizon.gios.gov.pl>
2004-12-07 23:54 ` Pablo Neira
2004-12-08 0:33 ` Krzysztof Oledzki
2004-12-08 0:52 ` Simon Kirby
[not found] ` <Pine.LNX.4.53.0412101310210.1288@bizon.gios.gov.pl>
2004-12-10 13:10 ` Simon Kirby
[not found] ` <Pine.LNX.4.53.0412101439530.6072@bizon.gios.gov.pl>
2004-12-10 14:49 ` Simon Kirby
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.