使用如下的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_CONNTRAnotrack规则设置了之后,将不对此连接建立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
转载请注明:duha.net » iptables notrack 跳过连接跟踪