iptables源码---tcp端口策略 解析

===================userspace===============================

/* Include file for additions: new matches and targets. */
struct xtables_match {
    /*
     * ABI/API version this module requires. Must be first member,
     * as the rest of this struct may be subject to ABI changes.
     */
    const char *version;

    struct xtables_match *next;

    const char *name;
    const char *real_name;

    /* Revision of match (0 by default). */
    uint8_t revision;

    /* Extension flags */
    uint8_t ext_flags;

    uint16_t family;

    /* Size of match data. */
    size_t size;

    /* Size of match data relevant for userspace comparison purposes */
    size_t userspacesize;

    /* Function which prints out usage message. */
    void (*help)(void);

    /* Initialize the match. */
    void (*init)(struct xt_entry_match *m);

    /* Function which parses command options; returns true if it
           ate an option */
    /* entry is struct ipt_entry for example */
    int (*parse)(int c, char **argv, int invert, unsigned int *flags,
             const void *entry,
             struct xt_entry_match **match);

    /* Final check; exit if not ok. */
    void (*final_check)(unsigned int flags);

    /* Prints out the match iff non-NULL: put space at end */
    /* ip is struct ipt_ip * for example */
    void (*print)(const void *ip,
              const struct xt_entry_match *match, int numeric);

    /* Saves the match info in parsable form to stdout. */
    /* ip is struct ipt_ip * for example */
    void (*save)(const void *ip, const struct xt_entry_match *match);

    /* Print match name or alias */
    const char *(*alias)(const struct xt_entry_match *match);

    /* Pointer to list of extra command-line options */
    const struct option *extra_opts;

    /* New parser */
    void (*x6_parse)(struct xt_option_call *);
    void (*x6_fcheck)(struct xt_fcheck_call *);
    const struct xt_option_entry *x6_options;

    /* Translate iptables to nft */
    int (*xlate)(struct xt_xlate *xl,
             const struct xt_xlate_mt_params *params);

    /* Size of per-extension instance extra "global" scratch space */
    size_t udata_size;

    /* Ignore these men behind the curtain: */
    void *udata;
    unsigned int option_offset;
    struct xt_entry_match *m;
    unsigned int mflags;
    unsigned int loaded; /* simulate loading so options are merged properly */
};

struct xt_tcp 

/* TCP match stuff */
struct xt_tcp {
    __u16 spts[2];    /* source port range */
    __u16 dpts[2];    /* destination port range */
    __u8 option;      /* TCP Option iff non-zero */
    __u8 flg_mask;    /* Tcp flags mask byte */
    __u8 flg_cmp;     /* Tcp flags compare byte */
    __u8 invflags;    /* Inverse flags */
};
static struct xtables_match tcp_match = {
    .family        = NFPROTO_UNSPEC,
    .name          = "tcp",
    .version       = XTABLES_VERSION,
    .size          = XT_ALIGN(sizeof(struct xt_tcp)),
    .userspacesize = XT_ALIGN(sizeof(struct xt_tcp)),
    .help          = tcp_help,
    .init          = tcp_init,
    .parse         = tcp_parse,
    .print         = tcp_print,
    .save          = tcp_save,
    .extra_opts    = tcp_opts,
    .xlate         = tcp_xlate,
};
static const struct option tcp_optes[] = {
    {.name = "source-port",     .has_arg = true,     .val = '1'},
    {.name = "sport",           .has_arg = true,     .val = '1'},
    {.name = "destination-port",.has_arg = true,     .val = '2'},
    {.name = "dport",           .has_arg = true,     .val = '2'},
    {.name = "syn",             .has_arg = true,     .val = '3'},
    {.name = "tcp-flags",       .has_arg = true,     .val = '4'},
    {.name = "tcp-option",      .has_arg = true,     .val = '5'},
};

 

#define XT_FUNCTION_MAXNAMELEN 30
#define XT_EXTENSION_MAXNAMELEN 29
#define XT_TABLE_MAXNAMELEN 32

struct xt_entry_match {
    union {
        struct {
            __u16 match_size;

            /* Used by userspace */
            char name[XT_EXTENSION_MAXNAMELEN]
        } user;
        struct {
            __u16 match_size;

            /* Used inside the kernel */
            struct xt_match *match;
        } kernel;

        /* Total length */
        __u16 match_size;
    } u;

    unsigned char data[0];
};
#define TCP_SRC_PORTS 0X01
#define TCP_DST_PORTS 0X02
#define TCP_FLAGS 0X04
#define TCP_OPTION 0X08

static int
tcp_parse(int c, char **argv, int invert, unsigned int *flags,
            const void *entry, struct xt_entry_match **match)
{
    struct xt_tcp *tcpinfo = (struct xt_tcp *)(*match)->data;

    switch (c) {
    case '1':
        ...
        break;
    case '2':
        if (*flags & TCP_DST_PORTS)
            xtables_error(PARAMETER_PROBLEM,
                    "Only one '--destination-port' allowed");
        parse_tcp_ports(optarg, tcpinfo->dpts);    // 将设置的端口赋值到tcpinfo->dpts中
        if (invert)
            tcpinfo->invflags |= XT_TCP_NV_DSTPT;
        *flags |= TCP_DST_PORTS;
        break;
    case ...
    }

    return 1;
}

============================kernel===================================

static struct xt_match tcpudp_mt_reg[] __read_mostly = {
    {
        .name        = "tcp",
        .family      = NFPROTO_IPV4,
        .checkentry  = tcp_mt_check,
        .match       = tcp_mt,
        .matchsize   = sizeof(struct xt_tcp),
        .proto       = IPPROTO_TCP,
        .me          = THIS_MODULE,
    }
    ...
};
static bool tcp_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
    const struct tcphdr *th;
    struct tcphdr _tcph;
    const struct xt_tcp *tcpinfo = par->matchinfo;

    if (par->fragoff != 0) {
        /* To quote Alan:

           Don't allow a fragment of TCP 8 bytes in. Nobody normal
           causes this. Its a cracker trying to break in by doing a
           flag overwrite to pass the direction checks.
        */
        if (par->fragoff == 1) {
            pr_debug("Dropping evil TCP offset=1 frag.\n");
            par->hotdrop = true;
        }   
        /* Must not be a fragment. */
        return false;
    }

#define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg)))

    th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
    if (th == NULL) {
     /* We've been asked to examine this packet, and we
        can't. Hence, no choice but to drop*/
        pr_debug("Dropping evil TCP offset=0 tinygram.\n");
        par->hotdrop = true;
        return false;
    }

    if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
            ntohs(th->source),
            !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
        return false;
    if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
            ntohs(th->dest),
            !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
        return false;
    if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
              == tcpinfo->flg_cmp,
              XT_TCP_INV_FLAGS))
        return false;
    if (tcpinfo->option) {
        if (th->doff * 4 < sizeof(_tcph)) {
            par->hotdrop = true;
            return false;
        }
   if (!tcp_find_option(tcpinfo->option, skb, par->thoff,
                     th->doff*4 - sizeof(_tcph),
                     tcpinfo->invflags & XT_TCP_INV_OPTION,
                     &par->hotdrop))
            return false;
    }
    return true;
}

xt_action_param中会将某条规则带入过来,然后再kernel的分析函数中(tcp_mt)对当前数据包进行分析。如果当前数据包符合xt_action_param带入的规则,则将返回true;否则返回false,并且在解析的过程中,存在明显的错误(如代码中,进行端口的判断,结果网络包中对传输层的头都不存在),除了返回错误之外,还将xt_action_param中的hotdrop设置为true(par->hotdrop = true),以便于之上层能够直接将数据进行drop等操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值