diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 3e0cccae5636..202d7fa09483 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -125,7 +125,7 @@ enum tcp_bit_set { | |||
125 | * CLOSE_WAIT: ACK seen (after FIN) | 125 | * CLOSE_WAIT: ACK seen (after FIN) |
126 | * LAST_ACK: FIN seen (after FIN) | 126 | * LAST_ACK: FIN seen (after FIN) |
127 | * TIME_WAIT: last ACK seen | 127 | * TIME_WAIT: last ACK seen |
128 | * CLOSE: closed connection | 128 | * CLOSE: closed connection (RST) |
129 | * | 129 | * |
130 | * LISTEN state is not used. | 130 | * LISTEN state is not used. |
131 | * | 131 | * |
@@ -824,7 +824,21 @@ static int tcp_packet(struct nf_conn *ct, | |||
824 | case TCP_CONNTRACK_SYN_SENT: | 824 | case TCP_CONNTRACK_SYN_SENT: |
825 | if (old_state < TCP_CONNTRACK_TIME_WAIT) | 825 | if (old_state < TCP_CONNTRACK_TIME_WAIT) |
826 | break; | 826 | break; |
827 | if ((ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_CLOSE_INIT) | 827 | /* RFC 1122: "When a connection is closed actively, |
828 | * it MUST linger in TIME-WAIT state for a time 2xMSL | ||
829 | * (Maximum Segment Lifetime). However, it MAY accept | ||
830 | * a new SYN from the remote TCP to reopen the connection | ||
831 | * directly from TIME-WAIT state, if..." | ||
832 | * We ignore the conditions because we are in the | ||
833 | * TIME-WAIT state anyway. | ||
834 | * | ||
835 | * Handle aborted connections: we and the server | ||
836 | * think there is an existing connection but the client | ||
837 | * aborts it and starts a new one. | ||
838 | */ | ||
839 | if (((ct->proto.tcp.seen[dir].flags | ||
840 | | ct->proto.tcp.seen[!dir].flags) | ||
841 | & IP_CT_TCP_FLAG_CLOSE_INIT) | ||
828 | || (ct->proto.tcp.last_dir == dir | 842 | || (ct->proto.tcp.last_dir == dir |
829 | && ct->proto.tcp.last_index == TCP_RST_SET)) { | 843 | && ct->proto.tcp.last_index == TCP_RST_SET)) { |
830 | /* Attempt to reopen a closed/aborted connection. | 844 | /* Attempt to reopen a closed/aborted connection. |
@@ -838,15 +852,22 @@ static int tcp_packet(struct nf_conn *ct, | |||
838 | case TCP_CONNTRACK_IGNORE: | 852 | case TCP_CONNTRACK_IGNORE: |
839 | /* Ignored packets: | 853 | /* Ignored packets: |
840 | * | 854 | * |
855 | * Our connection entry may be out of sync, so ignore | ||
856 | * packets which may signal the real connection between | ||
857 | * the client and the server. | ||
858 | * | ||
841 | * a) SYN in ORIGINAL | 859 | * a) SYN in ORIGINAL |
842 | * b) SYN/ACK in REPLY | 860 | * b) SYN/ACK in REPLY |
843 | * c) ACK in reply direction after initial SYN in original. | 861 | * c) ACK in reply direction after initial SYN in original. |
862 | * | ||
863 | * If the ignored packet is invalid, the receiver will send | ||
864 | * a RST we'll catch below. | ||
844 | */ | 865 | */ |
845 | if (index == TCP_SYNACK_SET | 866 | if (index == TCP_SYNACK_SET |
846 | && ct->proto.tcp.last_index == TCP_SYN_SET | 867 | && ct->proto.tcp.last_index == TCP_SYN_SET |
847 | && ct->proto.tcp.last_dir != dir | 868 | && ct->proto.tcp.last_dir != dir |
848 | && ntohl(th->ack_seq) == ct->proto.tcp.last_end) { | 869 | && ntohl(th->ack_seq) == ct->proto.tcp.last_end) { |
849 | /* This SYN/ACK acknowledges a SYN that we earlier | 870 | /* b) This SYN/ACK acknowledges a SYN that we earlier |
850 | * ignored as invalid. This means that the client and | 871 | * ignored as invalid. This means that the client and |
851 | * the server are both in sync, while the firewall is | 872 | * the server are both in sync, while the firewall is |
852 | * not. We kill this session and block the SYN/ACK so | 873 | * not. We kill this session and block the SYN/ACK so |
@@ -870,7 +891,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
870 | write_unlock_bh(&tcp_lock); | 891 | write_unlock_bh(&tcp_lock); |
871 | if (LOG_INVALID(IPPROTO_TCP)) | 892 | if (LOG_INVALID(IPPROTO_TCP)) |
872 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 893 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
873 | "nf_ct_tcp: invalid packed ignored "); | 894 | "nf_ct_tcp: invalid packet ignored "); |
874 | return NF_ACCEPT; | 895 | return NF_ACCEPT; |
875 | case TCP_CONNTRACK_MAX: | 896 | case TCP_CONNTRACK_MAX: |
876 | /* Invalid packet */ | 897 | /* Invalid packet */ |
@@ -924,8 +945,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
924 | 945 | ||
925 | ct->proto.tcp.state = new_state; | 946 | ct->proto.tcp.state = new_state; |
926 | if (old_state != new_state | 947 | if (old_state != new_state |
927 | && (new_state == TCP_CONNTRACK_FIN_WAIT | 948 | && new_state == TCP_CONNTRACK_CLOSE) |
928 | || new_state == TCP_CONNTRACK_CLOSE)) | ||
929 | ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; | 949 | ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; |
930 | timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans | 950 | timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans |
931 | && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans | 951 | && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans |