notrack跳过连接跟踪

使用如下的iptables命令配置notrack,

iptables -t raw -A PREROUTING -i ens33 -p tcp --dport 80 --syn -j NOTRACK
或者
iptables -t raw -A PREROUTING -i ens33 -p tcp --dport 80 --syn  -j CT --notrack 

使用iptables查看配置的规则,当前内核已经将NOTRACK目标设置为废弃状态,建议使用第二种配置方法。

$ iptables -L -t raw 
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
CT         tcp  --  anywhere             anywhere             tcp dpt:http flags:FIN,SYN,RST,ACK/SYN NOTRACK
CT         tcp  --  anywhere             anywhere             tcp dpt:http flags:FIN,SYN,RST,ACK/SYN CT notrack

NOTRACK目标

以下结构notrack_tg_reg定义了"NOTRACK"目标,其位于"raw"表中。

static struct xt_target notrack_tg_reg __read_mostly = {
    .name       = "NOTRACK",
    .revision   = 0,
    .family     = NFPROTO_UNSPEC,
    .checkentry = notrack_chk,
    .target     = notrack_tg,
    .table      = "raw",
    .me     = THIS_MODULE,
};

处理函数notrack_tg如下,首先检查skb结构中_nfct结构是否为空,不为空的话,表明可能是由环回接口接收的报文,对此种报文不做处理。否则,对于接收到的报文,通过函数nf_ct_set设置其关联的nf_conntrack的IP_CT_UNTRACKED标志。

static unsigned int notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
{   
    /* Previously seen (loopback)? Ignore. */
    if (skb->_nfct != 0)
        return XT_CONTINUE;
    
    nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
    
    return XT_CONTINUE;

CT目标和notrack标志

CT目标注册了三个版本的xt结构,以下以revision=2为例,与上节一样,其注册在raw表中。

static struct xt_target xt_ct_tg_reg[] __read_mostly = {
    ...
    {
        .name       = "CT",
        .family     = NFPROTO_UNSPEC,
        .revision   = 2,
        .targetsize = sizeof(struct xt_ct_target_info_v1),
        .usersize   = offsetof(struct xt_ct_target_info, ct),
        .checkentry = xt_ct_tg_check_v2,
        .destroy    = xt_ct_tg_destroy_v1,
        .target     = xt_ct_target_v1,
        .table      = "raw",
        .me     = THIS_MODULE,
    },
};

检查函数xt_ct_tg_check_v2的核心处理函数为xt_ct_tg_check,对于其它两个版本,也是此核心处理函数。如下,如果设置了–notrack,此处直接返回,不做处理。

static int xt_ct_tg_check(const struct xt_tgchk_param *par, struct xt_ct_target_info_v1 *info)
{
    if (info->flags & XT_CT_NOTRACK) {
        ct = NULL;
        goto out;
    }

处理函数如下的xt_ct_target_v1,其核心处理也是调用的上一节中介绍的函数xt_ct_target。

static unsigned int xt_ct_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
{
    const struct xt_ct_target_info_v1 *info = par->targinfo;
    struct nf_conn *ct = info->ct;

    return xt_ct_target(skb, ct);
}

跳过conntrack建立

在如下conntrack入口函数nf_conntrack_in中,如果报文设置了IP_CT_UNTRACKED标志,直接返回NF_ACCEPT。

unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
{
    enum ip_conntrack_info ctinfo;
	
    tmpl = nf_ct_get(skb, &ctinfo);
    if (tmpl || ctinfo == IP_CT_UNTRACKED) {
        /* Previously seen (loopback or untracked)?  Ignore. */
        if ((tmpl && !nf_ct_is_template(tmpl)) || ctinfo == IP_CT_UNTRACKED) {
            NF_CT_STAT_INC_ATOMIC(state->net, ignore);
            return NF_ACCEPT;
        }

由于PREROUTING点上,之前的raw表中的notrack规则优先级为NF_IP_PRI_RAW,高于以上的conntrack处理函数的优先级NF_IP_PRI_CONNTRACK。notrack规则设置了之后,将不对此连接建立conntrack结构,不进行追踪。

enum nf_ip_hook_priorities {
    NF_IP_PRI_FIRST = INT_MIN,
    NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
    NF_IP_PRI_CONNTRACK_DEFRAG = -400,
    NF_IP_PRI_RAW = -300,
    NF_IP_PRI_SELINUX_FIRST = -225,
    NF_IP_PRI_CONNTRACK = -200,

内核版本 5.0

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页