searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Expect conntrack

2023-06-02 02:23:43
5
0
# cat expect_test.c
MODULE_DESCRIPTION("expect helper test");
struct test_proto {
    int type;
    int port;
    union nf_inet_addr addr;
};
 
static int test_help(struct sk_buff *skb,
        unsigned int protoff,
        struct nf_conn *ct,
        enum ip_conntrack_info ctinfo)
{
    unsigned int dataoff, datalen;
    const struct tcphdr *th;
    struct tcphdr _tcph;
    int ret;
    char *dt_ptr;
    struct nf_conntrack_expect *exp;
    int dir = CTINFO2DIR(ctinfo);
    struct test_proto prot = {0};
    uint16_t port = ntohs((uint16_t)prot.port);
    char test_buffer[512];
 
    if (ctinfo != IP_CT_ESTABLISHED
        && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
        return NF_ACCEPT;
    }
 
    th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
    dataoff = protoff + th->doff * 4;
    datalen = skb->len - dataoff;
    dt_ptr = skb_header_pointer(skb, dataoff, datalen, test_buffer);
    //get proto header
    memcpy(&prot, dt_ptr, sizeof(struct test_proto));
    if (prot.type != 100) { 
        ret = NF_ACCEPT;
        goto out;
    }
 
    exp = nf_ct_expect_alloc(ct);
    port = ntohs((uint16_t)prot.port);
    nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, AF_INET,
              &ct->tuplehash[dir].tuple.src.u3, &prot.addr,
              IPPROTO_TCP, NULL, &port);
    if (nf_ct_expect_related(exp) != 0)
        ret = NF_DROP;
    else
        ret = NF_ACCEPT;
out:
    return ret;
}
static const struct nf_conntrack_expect_policy test_policy = {
    .max_expected    = 10,
    .timeout    = 50 * 60,
};
 
#define PORT 5000
 
static struct nf_conntrack_helper test = {
    .name = "test",
    .me = THIS_MODULE,
    .tuple.src.l3num = AF_INET,
    .tuple.src.u.tcp.port = cpu_to_be16(5000),
    .tuple.dst.protonum = IPPROTO_TCP,
    .help = test_help,
    .expect_policy = &test_policy,
};
 
static void nf_conntrack_test_fini(void)
{
    nf_conntrack_helper_unregister(&test);
}
 
static int __init nf_conntrack_test_init(void)
{
    int ret = nf_conntrack_helper_register(&test);
 
    return ret;
}
 
module_init(nf_conntrack_test_init);
module_exit(nf_conntrack_test_fini);
 
 
usage:
1. 本地防火墙只允许访问192.168.0.2:2152
iptables -A OUTPUT -m conntrack --ctstatus EXPECTED -j ACCEPT
iptables -A OUTPUT -d 192.168.0.2 -j ACCEPT
iptables -A OUTPUT -j DROP
 
iptables -t raw -A OUTPUT -d 192.168.0.2 -p tcp --dport 12345 -j CT  --helper test
 
2. 本地connect 192.168.0.2:2152后发送定义test_proto协议
struct test_proto {
        int type;
        int port;
        in_addr_t addr;
};
 
struct test_proto ap = {0};
ap.addr = inet_addr("192.168.0.3");
ap.type = 100;
ap.port = 2152;
len = sizeof(struct aa_proto);
sbuf = ≈
 
write(sock, (char *)sbuf, len);
 
3. 本地connect 192.168.0.3:2152成功, 第2步建立了一个expect conntrack,可以通过第1步的第一条firewall规则
0条评论
0 / 1000
w****n
15文章数
0粉丝数
w****n
15 文章 | 0 粉丝