2016-12-17 22:18 GMT+08:00 Liping Zhang <zlpnobody@xxxxxxxxx>: > > For loopback connection, the request packets will traverse: > OUTPUT->POSTROUTING->PREROUTING->INPUT > and the source ip will be modified in nat POSTROUTING hook. > > Meanwhile the reply packets will also traverse: > OUTPUT->POSTROUTING->PREROUTING->INPUT > and if nat OUTPUT hook exist, the destination ip will be modified > in it, and re-route will happen. Otherwise, the destination ip will > be modified at nat PREROUTING hook, and the dst entry will > be dropped. In such situation(i.e. nat OUTPUT doesn't exist), > we will try to do routing lookup and packets will be dropped > at ip_route_input_slow->martian_destination. > > Furthermore, if ipt_rpfilter is configured, the reply packet maybe > dropped at there. > > In iptables, nat output chain always exists, so there's no > such problem. > > But I think that enforcing the user to add a nat output chain > in nftables is not a good idea, so probably we need a following > patch(I only list the ipv4 part): > > diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c > b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c > index f8aad03..5bc9b22 100644 > --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c > +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c > @@ -344,8 +344,21 @@ nf_nat_ipv4_in(void *priv, struct sk_buff *skb, > > ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); > if (ret != NF_DROP && ret != NF_STOLEN && > - daddr != ip_hdr(skb)->daddr) > - skb_dst_drop(skb); > + daddr != ip_hdr(skb)->daddr) { > + const struct rtable *rt = skb_rtable(skb); > + int err; > + > + if (rt) { > + if (rt->rt_flags & RTCF_LOCAL) { > + err = ip_route_me_harder(state->net, skb, > + RTN_UNSPEC); > + if (err < 0) > + ret = NF_DROP_ERR(err); > + } else { > + skb_dst_drop(skb); > + } > + } > + } > > return ret; > } > Please ignore the above patch, it's incorrect that we use ip_route_output_key for the incoming packets. Maybe the below one will be better, but I'm not sure whether this will break some special use cases or not: diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index f8aad03..d358670 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -344,8 +344,13 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && - daddr != ip_hdr(skb)->daddr) + daddr != ip_hdr(skb)->daddr) { + if (state->in->flags & IFF_LOOPBACK || + skb->pkt_type == PACKET_LOOPBACK) + return ret; + skb_dst_drop(skb); + } -- To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html