Hi again. I modified your patch as below and now synproxy send mss values as it should be. Soom I will test it on real environment. I also have another question. When I don't provide --wscale option, both client syn-ack an server syn packets have empty wscale. When I don't provide --mss option, I realized firewall not set mss value on client syn-ack, but it sets mss on server syn. Is that what suppose to happen? diff -rupN a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c --- a/net/ipv4/netfilter/ipt_SYNPROXY.c 2019-06-19 09:51:40.163633231 +0300 +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c 2019-06-20 13:32:18.893025129 +0300 @@ -71,13 +71,13 @@ free_nskb: static void synproxy_send_client_synack(struct net *net, const struct sk_buff *skb, const struct tcphdr *th, - const struct synproxy_options *opts) + const struct synproxy_options *opts, const u16 *client_mssinfo) { struct sk_buff *nskb; struct iphdr *iph, *niph; struct tcphdr *nth; unsigned int tcp_hdr_size; - u16 mss = opts->mss; + u16 mss = *client_mssinfo; iph = ip_hdr(skb); @@ -266,6 +265,7 @@ synproxy_tg4(struct sk_buff *skb, const struct synproxy_net *snet = synproxy_pernet(net); struct synproxy_options opts = {}; struct tcphdr *th, _th; + u16 client_mssinfo; if (nf_ip_checksum(skb, xt_hooknum(par), par->thoff, IPPROTO_TCP)) return NF_DROP; @@ -285,6 +285,8 @@ synproxy_tg4(struct sk_buff *skb, const opts.options |= XT_SYNPROXY_OPT_ECN; opts.options &= info->options; + client_mssinfo = opts.mss; + opts.mss = info->mss; if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP) synproxy_init_timestamp_cookie(info, &opts); else @@ -292,7 +294,7 @@ synproxy_tg4(struct sk_buff *skb, const XT_SYNPROXY_OPT_SACK_PERM | XT_SYNPROXY_OPT_ECN); - synproxy_send_client_synack(net, skb, th, &opts); + synproxy_send_client_synack(net, skb, th, &opts, &client_mssinfo); consume_skb(skb); return NF_STOLEN; } else if (th->ack && !(th->fin || th->rst || th->syn)) {