linux/net/netfilter/xt_TPROXY.c
<<
>>
Prefs
   1/*
   2 * Transparent proxy support for Linux/iptables
   3 *
   4 * Copyright (c) 2006-2010 BalaBit IT Ltd.
   5 * Author: Balazs Scheidler, Krisztian Kovacs
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 */
  12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13#include <linux/module.h>
  14#include <linux/skbuff.h>
  15#include <linux/ip.h>
  16#include <net/checksum.h>
  17#include <net/udp.h>
  18#include <net/tcp.h>
  19#include <net/inet_sock.h>
  20#include <net/inet_hashtables.h>
  21#include <linux/inetdevice.h>
  22#include <linux/netfilter/x_tables.h>
  23#include <linux/netfilter_ipv4/ip_tables.h>
  24
  25#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
  26
  27#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  28#define XT_TPROXY_HAVE_IPV6 1
  29#include <net/if_inet6.h>
  30#include <net/addrconf.h>
  31#include <net/inet6_hashtables.h>
  32#include <linux/netfilter_ipv6/ip6_tables.h>
  33#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
  34#endif
  35
  36#include <linux/netfilter/xt_TPROXY.h>
  37
  38enum nf_tproxy_lookup_t {
  39         NFT_LOOKUP_LISTENER,
  40         NFT_LOOKUP_ESTABLISHED,
  41};
  42
  43static bool tproxy_sk_is_transparent(struct sock *sk)
  44{
  45        switch (sk->sk_state) {
  46        case TCP_TIME_WAIT:
  47                if (inet_twsk(sk)->tw_transparent)
  48                        return true;
  49                break;
  50        case TCP_NEW_SYN_RECV:
  51                if (inet_rsk(inet_reqsk(sk))->no_srccheck)
  52                        return true;
  53                break;
  54        default:
  55                if (inet_sk(sk)->transparent)
  56                        return true;
  57        }
  58
  59        sock_gen_put(sk);
  60        return false;
  61}
  62
  63static inline __be32
  64tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
  65{
  66        struct in_device *indev;
  67        __be32 laddr;
  68
  69        if (user_laddr)
  70                return user_laddr;
  71
  72        laddr = 0;
  73        rcu_read_lock();
  74        indev = __in_dev_get_rcu(skb->dev);
  75        for_primary_ifa(indev) {
  76                laddr = ifa->ifa_local;
  77                break;
  78        } endfor_ifa(indev);
  79        rcu_read_unlock();
  80
  81        return laddr ? laddr : daddr;
  82}
  83
  84/*
  85 * This is used when the user wants to intercept a connection matching
  86 * an explicit iptables rule. In this case the sockets are assumed
  87 * matching in preference order:
  88 *
  89 *   - match: if there's a fully established connection matching the
  90 *     _packet_ tuple, it is returned, assuming the redirection
  91 *     already took place and we process a packet belonging to an
  92 *     established connection
  93 *
  94 *   - match: if there's a listening socket matching the redirection
  95 *     (e.g. on-port & on-ip of the connection), it is returned,
  96 *     regardless if it was bound to 0.0.0.0 or an explicit
  97 *     address. The reasoning is that if there's an explicit rule, it
  98 *     does not really matter if the listener is bound to an interface
  99 *     or to 0. The user already stated that he wants redirection
 100 *     (since he added the rule).
 101 *
 102 * Please note that there's an overlap between what a TPROXY target
 103 * and a socket match will match. Normally if you have both rules the
 104 * "socket" match will be the first one, effectively all packets
 105 * belonging to established connections going through that one.
 106 */
 107static inline struct sock *
 108nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 109                      const __be32 saddr, const __be32 daddr,
 110                      const __be16 sport, const __be16 dport,
 111                      const struct net_device *in,
 112                      const enum nf_tproxy_lookup_t lookup_type)
 113{
 114        struct sock *sk;
 115
 116        switch (protocol) {
 117        case IPPROTO_TCP:
 118                switch (lookup_type) {
 119                case NFT_LOOKUP_LISTENER:
 120                        sk = inet_lookup_listener(net, &tcp_hashinfo,
 121                                                    saddr, sport,
 122                                                    daddr, dport,
 123                                                    in->ifindex);
 124
 125                        /* NOTE: we return listeners even if bound to
 126                         * 0.0.0.0, those are filtered out in
 127                         * xt_socket, since xt_TPROXY needs 0 bound
 128                         * listeners too
 129                         */
 130                        break;
 131                case NFT_LOOKUP_ESTABLISHED:
 132                        sk = inet_lookup_established(net, &tcp_hashinfo,
 133                                                    saddr, sport, daddr, dport,
 134                                                    in->ifindex);
 135                        break;
 136                default:
 137                        BUG();
 138                }
 139                break;
 140        case IPPROTO_UDP:
 141                sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
 142                                     in->ifindex);
 143                if (sk) {
 144                        int connected = (sk->sk_state == TCP_ESTABLISHED);
 145                        int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
 146
 147                        /* NOTE: we return listeners even if bound to
 148                         * 0.0.0.0, those are filtered out in
 149                         * xt_socket, since xt_TPROXY needs 0 bound
 150                         * listeners too
 151                         */
 152                        if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
 153                            (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
 154                                sock_put(sk);
 155                                sk = NULL;
 156                        }
 157                }
 158                break;
 159        default:
 160                WARN_ON(1);
 161                sk = NULL;
 162        }
 163
 164        pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
 165                 protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
 166
 167        return sk;
 168}
 169
 170#ifdef XT_TPROXY_HAVE_IPV6
 171static inline struct sock *
 172nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
 173                      const struct in6_addr *saddr, const struct in6_addr *daddr,
 174                      const __be16 sport, const __be16 dport,
 175                      const struct net_device *in,
 176                      const enum nf_tproxy_lookup_t lookup_type)
 177{
 178        struct sock *sk;
 179
 180        switch (protocol) {
 181        case IPPROTO_TCP:
 182                switch (lookup_type) {
 183                case NFT_LOOKUP_LISTENER:
 184                        sk = inet6_lookup_listener(net, &tcp_hashinfo,
 185                                                   saddr, sport,
 186                                                   daddr, ntohs(dport),
 187                                                   in->ifindex);
 188
 189                        /* NOTE: we return listeners even if bound to
 190                         * 0.0.0.0, those are filtered out in
 191                         * xt_socket, since xt_TPROXY needs 0 bound
 192                         * listeners too
 193                         */
 194                        break;
 195                case NFT_LOOKUP_ESTABLISHED:
 196                        sk = __inet6_lookup_established(net, &tcp_hashinfo,
 197                                                        saddr, sport, daddr, ntohs(dport),
 198                                                        in->ifindex);
 199                        break;
 200                default:
 201                        BUG();
 202                }
 203                break;
 204        case IPPROTO_UDP:
 205                sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
 206                                     in->ifindex);
 207                if (sk) {
 208                        int connected = (sk->sk_state == TCP_ESTABLISHED);
 209                        int wildcard = ipv6_addr_any(&sk->sk_v6_rcv_saddr);
 210
 211                        /* NOTE: we return listeners even if bound to
 212                         * 0.0.0.0, those are filtered out in
 213                         * xt_socket, since xt_TPROXY needs 0 bound
 214                         * listeners too
 215                         */
 216                        if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
 217                            (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
 218                                sock_put(sk);
 219                                sk = NULL;
 220                        }
 221                }
 222                break;
 223        default:
 224                WARN_ON(1);
 225                sk = NULL;
 226        }
 227
 228        pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
 229                 protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
 230
 231        return sk;
 232}
 233#endif
 234
 235/**
 236 * tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections
 237 * @skb:        The skb being processed.
 238 * @laddr:      IPv4 address to redirect to or zero.
 239 * @lport:      TCP port to redirect to or zero.
 240 * @sk:         The TIME_WAIT TCP socket found by the lookup.
 241 *
 242 * We have to handle SYN packets arriving to TIME_WAIT sockets
 243 * differently: instead of reopening the connection we should rather
 244 * redirect the new connection to the proxy if there's a listener
 245 * socket present.
 246 *
 247 * tproxy_handle_time_wait4() consumes the socket reference passed in.
 248 *
 249 * Returns the listener socket if there's one, the TIME_WAIT socket if
 250 * no such listener is found, or NULL if the TCP header is incomplete.
 251 */
 252static struct sock *
 253tproxy_handle_time_wait4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 254                        struct sock *sk)
 255{
 256        const struct iphdr *iph = ip_hdr(skb);
 257        struct tcphdr _hdr, *hp;
 258
 259        hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
 260        if (hp == NULL) {
 261                inet_twsk_put(inet_twsk(sk));
 262                return NULL;
 263        }
 264
 265        if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
 266                /* SYN to a TIME_WAIT socket, we'd rather redirect it
 267                 * to a listener socket if there's one */
 268                struct sock *sk2;
 269
 270                sk2 = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
 271                                            iph->saddr, laddr ? laddr : iph->daddr,
 272                                            hp->source, lport ? lport : hp->dest,
 273                                            skb->dev, NFT_LOOKUP_LISTENER);
 274                if (sk2) {
 275                        inet_twsk_deschedule_put(inet_twsk(sk));
 276                        sk = sk2;
 277                }
 278        }
 279
 280        return sk;
 281}
 282
 283/* assign a socket to the skb -- consumes sk */
 284static void
 285nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
 286{
 287        skb_orphan(skb);
 288        skb->sk = sk;
 289        skb->destructor = sock_edemux;
 290}
 291
 292static unsigned int
 293tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport,
 294           u_int32_t mark_mask, u_int32_t mark_value)
 295{
 296        const struct iphdr *iph = ip_hdr(skb);
 297        struct udphdr _hdr, *hp;
 298        struct sock *sk;
 299
 300        hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
 301        if (hp == NULL)
 302                return NF_DROP;
 303
 304        /* check if there's an ongoing connection on the packet
 305         * addresses, this happens if the redirect already happened
 306         * and the current packet belongs to an already established
 307         * connection */
 308        sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
 309                                   iph->saddr, iph->daddr,
 310                                   hp->source, hp->dest,
 311                                   skb->dev, NFT_LOOKUP_ESTABLISHED);
 312
 313        laddr = tproxy_laddr4(skb, laddr, iph->daddr);
 314        if (!lport)
 315                lport = hp->dest;
 316
 317        /* UDP has no TCP_TIME_WAIT state, so we never enter here */
 318        if (sk && sk->sk_state == TCP_TIME_WAIT)
 319                /* reopening a TIME_WAIT connection needs special handling */
 320                sk = tproxy_handle_time_wait4(skb, laddr, lport, sk);
 321        else if (!sk)
 322                /* no, there's no established connection, check if
 323                 * there's a listener on the redirected addr/port */
 324                sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
 325                                           iph->saddr, laddr,
 326                                           hp->source, lport,
 327                                           skb->dev, NFT_LOOKUP_LISTENER);
 328
 329        /* NOTE: assign_sock consumes our sk reference */
 330        if (sk && tproxy_sk_is_transparent(sk)) {
 331                /* This should be in a separate target, but we don't do multiple
 332                   targets on the same rule yet */
 333                skb->mark = (skb->mark & ~mark_mask) ^ mark_value;
 334
 335                pr_debug("redirecting: proto %hhu %pI4:%hu -> %pI4:%hu, mark: %x\n",
 336                         iph->protocol, &iph->daddr, ntohs(hp->dest),
 337                         &laddr, ntohs(lport), skb->mark);
 338
 339                nf_tproxy_assign_sock(skb, sk);
 340                return NF_ACCEPT;
 341        }
 342
 343        pr_debug("no socket, dropping: proto %hhu %pI4:%hu -> %pI4:%hu, mark: %x\n",
 344                 iph->protocol, &iph->saddr, ntohs(hp->source),
 345                 &iph->daddr, ntohs(hp->dest), skb->mark);
 346        return NF_DROP;
 347}
 348
 349static unsigned int
 350tproxy_tg4_v0(struct sk_buff *skb, const struct xt_action_param *par)
 351{
 352        const struct xt_tproxy_target_info *tgi = par->targinfo;
 353
 354        return tproxy_tg4(skb, tgi->laddr, tgi->lport, tgi->mark_mask, tgi->mark_value);
 355}
 356
 357static unsigned int
 358tproxy_tg4_v1(struct sk_buff *skb, const struct xt_action_param *par)
 359{
 360        const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
 361
 362        return tproxy_tg4(skb, tgi->laddr.ip, tgi->lport, tgi->mark_mask, tgi->mark_value);
 363}
 364
 365#ifdef XT_TPROXY_HAVE_IPV6
 366
 367static inline const struct in6_addr *
 368tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr,
 369              const struct in6_addr *daddr)
 370{
 371        struct inet6_dev *indev;
 372        struct inet6_ifaddr *ifa;
 373        struct in6_addr *laddr;
 374
 375        if (!ipv6_addr_any(user_laddr))
 376                return user_laddr;
 377        laddr = NULL;
 378
 379        rcu_read_lock();
 380        indev = __in6_dev_get(skb->dev);
 381        if (indev)
 382                list_for_each_entry(ifa, &indev->addr_list, if_list) {
 383                        if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
 384                                continue;
 385
 386                        laddr = &ifa->addr;
 387                        break;
 388                }
 389        rcu_read_unlock();
 390
 391        return laddr ? laddr : daddr;
 392}
 393
 394/**
 395 * tproxy_handle_time_wait6 - handle IPv6 TCP TIME_WAIT reopen redirections
 396 * @skb:        The skb being processed.
 397 * @tproto:     Transport protocol.
 398 * @thoff:      Transport protocol header offset.
 399 * @par:        Iptables target parameters.
 400 * @sk:         The TIME_WAIT TCP socket found by the lookup.
 401 *
 402 * We have to handle SYN packets arriving to TIME_WAIT sockets
 403 * differently: instead of reopening the connection we should rather
 404 * redirect the new connection to the proxy if there's a listener
 405 * socket present.
 406 *
 407 * tproxy_handle_time_wait6() consumes the socket reference passed in.
 408 *
 409 * Returns the listener socket if there's one, the TIME_WAIT socket if
 410 * no such listener is found, or NULL if the TCP header is incomplete.
 411 */
 412static struct sock *
 413tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
 414                         const struct xt_action_param *par,
 415                         struct sock *sk)
 416{
 417        const struct ipv6hdr *iph = ipv6_hdr(skb);
 418        struct tcphdr _hdr, *hp;
 419        const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
 420
 421        hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
 422        if (hp == NULL) {
 423                inet_twsk_put(inet_twsk(sk));
 424                return NULL;
 425        }
 426
 427        if (hp->syn && !hp->rst && !hp->ack && !hp->fin) {
 428                /* SYN to a TIME_WAIT socket, we'd rather redirect it
 429                 * to a listener socket if there's one */
 430                struct sock *sk2;
 431
 432                sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
 433                                            &iph->saddr,
 434                                            tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
 435                                            hp->source,
 436                                            tgi->lport ? tgi->lport : hp->dest,
 437                                            skb->dev, NFT_LOOKUP_LISTENER);
 438                if (sk2) {
 439                        inet_twsk_deschedule_put(inet_twsk(sk));
 440                        sk = sk2;
 441                }
 442        }
 443
 444        return sk;
 445}
 446
 447static unsigned int
 448tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
 449{
 450        const struct ipv6hdr *iph = ipv6_hdr(skb);
 451        const struct xt_tproxy_target_info_v1 *tgi = par->targinfo;
 452        struct udphdr _hdr, *hp;
 453        struct sock *sk;
 454        const struct in6_addr *laddr;
 455        __be16 lport;
 456        int thoff = 0;
 457        int tproto;
 458
 459        tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
 460        if (tproto < 0) {
 461                pr_debug("unable to find transport header in IPv6 packet, dropping\n");
 462                return NF_DROP;
 463        }
 464
 465        hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
 466        if (hp == NULL) {
 467                pr_debug("unable to grab transport header contents in IPv6 packet, dropping\n");
 468                return NF_DROP;
 469        }
 470
 471        /* check if there's an ongoing connection on the packet
 472         * addresses, this happens if the redirect already happened
 473         * and the current packet belongs to an already established
 474         * connection */
 475        sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
 476                                   &iph->saddr, &iph->daddr,
 477                                   hp->source, hp->dest,
 478                                   par->in, NFT_LOOKUP_ESTABLISHED);
 479
 480        laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr);
 481        lport = tgi->lport ? tgi->lport : hp->dest;
 482
 483        /* UDP has no TCP_TIME_WAIT state, so we never enter here */
 484        if (sk && sk->sk_state == TCP_TIME_WAIT)
 485                /* reopening a TIME_WAIT connection needs special handling */
 486                sk = tproxy_handle_time_wait6(skb, tproto, thoff, par, sk);
 487        else if (!sk)
 488                /* no there's no established connection, check if
 489                 * there's a listener on the redirected addr/port */
 490                sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
 491                                           &iph->saddr, laddr,
 492                                           hp->source, lport,
 493                                           par->in, NFT_LOOKUP_LISTENER);
 494
 495        /* NOTE: assign_sock consumes our sk reference */
 496        if (sk && tproxy_sk_is_transparent(sk)) {
 497                /* This should be in a separate target, but we don't do multiple
 498                   targets on the same rule yet */
 499                skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
 500
 501                pr_debug("redirecting: proto %hhu %pI6:%hu -> %pI6:%hu, mark: %x\n",
 502                         tproto, &iph->saddr, ntohs(hp->source),
 503                         laddr, ntohs(lport), skb->mark);
 504
 505                nf_tproxy_assign_sock(skb, sk);
 506                return NF_ACCEPT;
 507        }
 508
 509        pr_debug("no socket, dropping: proto %hhu %pI6:%hu -> %pI6:%hu, mark: %x\n",
 510                 tproto, &iph->saddr, ntohs(hp->source),
 511                 &iph->daddr, ntohs(hp->dest), skb->mark);
 512
 513        return NF_DROP;
 514}
 515
 516static int tproxy_tg6_check(const struct xt_tgchk_param *par)
 517{
 518        const struct ip6t_ip6 *i = par->entryinfo;
 519
 520        if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&
 521            !(i->invflags & IP6T_INV_PROTO))
 522                return 0;
 523
 524        pr_info("Can be used only in combination with "
 525                "either -p tcp or -p udp\n");
 526        return -EINVAL;
 527}
 528#endif
 529
 530static int tproxy_tg4_check(const struct xt_tgchk_param *par)
 531{
 532        const struct ipt_ip *i = par->entryinfo;
 533
 534        if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
 535            && !(i->invflags & IPT_INV_PROTO))
 536                return 0;
 537
 538        pr_info("Can be used only in combination with "
 539                "either -p tcp or -p udp\n");
 540        return -EINVAL;
 541}
 542
 543static struct xt_target tproxy_tg_reg[] __read_mostly = {
 544        {
 545                .name           = "TPROXY",
 546                .family         = NFPROTO_IPV4,
 547                .table          = "mangle",
 548                .target         = tproxy_tg4_v0,
 549                .revision       = 0,
 550                .targetsize     = sizeof(struct xt_tproxy_target_info),
 551                .checkentry     = tproxy_tg4_check,
 552                .hooks          = 1 << NF_INET_PRE_ROUTING,
 553                .me             = THIS_MODULE,
 554        },
 555        {
 556                .name           = "TPROXY",
 557                .family         = NFPROTO_IPV4,
 558                .table          = "mangle",
 559                .target         = tproxy_tg4_v1,
 560                .revision       = 1,
 561                .targetsize     = sizeof(struct xt_tproxy_target_info_v1),
 562                .checkentry     = tproxy_tg4_check,
 563                .hooks          = 1 << NF_INET_PRE_ROUTING,
 564                .me             = THIS_MODULE,
 565        },
 566#ifdef XT_TPROXY_HAVE_IPV6
 567        {
 568                .name           = "TPROXY",
 569                .family         = NFPROTO_IPV6,
 570                .table          = "mangle",
 571                .target         = tproxy_tg6_v1,
 572                .revision       = 1,
 573                .targetsize     = sizeof(struct xt_tproxy_target_info_v1),
 574                .checkentry     = tproxy_tg6_check,
 575                .hooks          = 1 << NF_INET_PRE_ROUTING,
 576                .me             = THIS_MODULE,
 577        },
 578#endif
 579
 580};
 581
 582static int __init tproxy_tg_init(void)
 583{
 584        nf_defrag_ipv4_enable();
 585#ifdef XT_TPROXY_HAVE_IPV6
 586        nf_defrag_ipv6_enable();
 587#endif
 588
 589        return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 590}
 591
 592static void __exit tproxy_tg_exit(void)
 593{
 594        xt_unregister_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
 595}
 596
 597module_init(tproxy_tg_init);
 598module_exit(tproxy_tg_exit);
 599MODULE_LICENSE("GPL");
 600MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs");
 601MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
 602MODULE_ALIAS("ipt_TPROXY");
 603MODULE_ALIAS("ip6t_TPROXY");
 604