📄 drcom.c
字号:
todo = TODO_NONE; goto out; } */ /* Handshake ACK with data*/ if (oldtcpstate == TCP_STATE_SYN_RECV && skb->len > hdrlen && dir == CONN_DIR_ORIG && tcph->ack && !tcph->syn && (ntohl(tcph->ack_seq) == conn->seq[!dir].syn_seq+1) && (ntohl(tcph->seq) == conn->seq[dir].syn_seq+1) && !(conn->flags & CONN_F_AUTHSENT)) { todo = TODO_SEND_ACK | TODO_SEND_AUTH | TODO_ADJUST_SEQ; conn->flags |= CONN_F_AUTHSENT; goto out; } /* The first data packet */ if (oldtcpstate == TCP_STATE_ESTABLISHED && skb->len > hdrlen && dir == CONN_DIR_ORIG && tcph->ack && !tcph->syn /* && (ntohl(tcph->ack_seq) == conn->seq[!dir].syn_seq+1) *//* ftp server will send first */ && (ntohl(tcph->seq) == conn->seq[dir].syn_seq+1) && !(conn->flags & CONN_F_AUTHSENT)) { todo = TODO_SEND_AUTH | TODO_ADJUST_SEQ; conn->flags |= CONN_F_AUTHSENT; goto out; } /* * CONN_F_AUTHSENT not set, * and not the case to set CONN_F_AUTHSENT, * just bypass */ todo = TODO_NONE;out: __conn_refresh_timer(conn, tcp_timeouts[newstate]); write_unlock_bh(&state_lock); return todo;}static struct sk_buff *build_ack_skb(struct sk_buff *oskb){ struct iphdr *iph; struct tcphdr *tcph; struct sk_buff *skb; /* FIXME: Can we avoid the copy here? */ skb = skb_copy(oskb, GFP_ATOMIC); if (skb == NULL) return NULL; iph = ip_hdr(skb); tcph = (void *)skb->data + ip_hdrlen(skb); skb_trim(skb, (iph->ihl + tcph->doff) * 4); skb_shinfo(skb)->gso_segs = 1; skb_shinfo(skb)->gso_size = 0; skb_shinfo(skb)->gso_type = 0; skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; tcph->check = 0; tcph->check = tcp_v4_check(tcph->doff << 2, iph->saddr, iph->daddr, csum_partial((char *)tcph, tcph->doff << 2, skb->csum)); iph->tot_len = htons(skb->len); __ip_select_ident(iph, skb->dst, 0); ip_send_check(iph); return skb;}static struct sk_buff *build_auth_skb(struct sk_buff *oskb){ struct iphdr *iph; struct tcphdr *tcph; unsigned int hdrlen; struct sk_buff *skb; /* FIXME: Can we avoid the copy here? */ skb = skb_copy_expand(oskb, skb_headroom(oskb), CONN_AUTH_DATA_LEN, GFP_ATOMIC); if (skb == NULL) return NULL; iph = ip_hdr(skb); tcph = (void *)skb->data + ip_hdrlen(skb); hdrlen = (iph->ihl + tcph->doff) * 4; skb_trim(skb, hdrlen); skb_put(skb, CONN_AUTH_DATA_LEN); memcpy(skb->data + hdrlen, conn_auth_data, CONN_AUTH_DATA_LEN); skb_shinfo(skb)->gso_segs = 1; skb_shinfo(skb)->gso_size = 0; skb_shinfo(skb)->gso_type = 0; skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; tcph->check = 0; tcph->check = tcp_v4_check(skb->len-ip_hdrlen(skb), iph->saddr, iph->daddr, csum_partial((char *)tcph, skb->len-ip_hdrlen(skb), skb->csum)); iph->tot_len = htons(skb->len); __ip_select_ident(iph, skb->dst, 0); ip_send_check(iph); return skb;}static inline int is_our_packet(struct sk_buff *skb){ struct iphdr *iph = ip_hdr(skb); return (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP);}static inline int is_udp_packet(struct sk_buff *skb){ struct iphdr *iph = ip_hdr(skb); return (iph->protocol == IPPROTO_UDP);}static void conn_do_udp(struct sk_buff *oskb, int (*okfn)(struct sk_buff *)){ struct sk_buff *skb; struct iphdr *iph; struct udphdr *udph; unsigned short len; /* FIXME: Can we avoid the copy here? */ skb = skb_copy_expand(oskb, skb_headroom(oskb) + CONN_AUTH_DATA_LEN, 0, GFP_ATOMIC); if (skb == NULL) return; kfree_skb(oskb); iph = ip_hdr(skb); udph = (void *)iph + ip_hdrlen(skb); memcpy((void *)iph-CONN_AUTH_DATA_LEN, (void*)iph, ip_hdrlen(skb)+8); memcpy((void*)udph+8-CONN_AUTH_DATA_LEN, conn_auth_data, CONN_AUTH_DATA_LEN); skb_push(skb, CONN_AUTH_DATA_LEN); skb_reset_network_header(skb); iph = ip_hdr(skb); udph = (void *)iph + ip_hdrlen(skb); skb_shinfo(skb)->gso_segs = 1; skb_shinfo(skb)->gso_size = 0; skb_shinfo(skb)->gso_type = 0; skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; len = ntohs(udph->len) + CONN_AUTH_DATA_LEN; udph->len = htons(len); udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len, IPPROTO_UDP, csum_partial((unsigned char *)udph, len, 0)); /* ip stuff */ iph->tot_len = htons(skb->len); ip_send_check(iph); okfn(skb);}static int need_auth_input(struct sk_buff *skb){ u_int32_t saddr = ip_hdr(skb)->saddr; int i; for (i=0; i<conn_e_count; i++) if ((conn_e_addr[i].mask & saddr) == conn_e_addr[i].addr) return 0; return 1;}static int need_auth_output(struct sk_buff *skb){ u_int32_t daddr = ip_hdr(skb)->daddr; int i; for (i=0; i<conn_e_count; i++) if ((conn_e_addr[i].mask & daddr) == conn_e_addr[i].addr) return 0; return 1;}#define CONN_KEEPALIVE_TIMEOUT (2*60*HZ)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)#define kill_proc(pid, sig, priv) kill_pid(find_vpid(pid), sig, priv)#endifstatic void keepalive_func(unsigned long ul){ read_lock_bh(&mode_lock); if (track_mode != CONN_MODE_NONE && conn_autologout && conn_pid) kill_proc(conn_pid, SIGUSR1, 1); read_unlock_bh(&mode_lock);}static void init_keepalive_timer(void){ read_lock_bh(&mode_lock); if (track_mode != CONN_MODE_NONE && conn_autologout) { setup_timer(&conn_keepalive_timer, keepalive_func, 0); conn_keepalive_timer.expires = jiffies+CONN_KEEPALIVE_TIMEOUT; add_timer(&conn_keepalive_timer); } read_unlock_bh(&mode_lock);}/* under mode_lock */static void __refresh_keepalive_timer(void){ if (conn_autologout) mod_timer(&conn_keepalive_timer, jiffies+CONN_KEEPALIVE_TIMEOUT);}static void del_keepalive_timer(void){ read_lock_bh(&mode_lock); del_timer(&conn_keepalive_timer); read_unlock_bh(&mode_lock);}static unsigned int preroute_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){ struct tcp_tuplehash *hash; unsigned int todo; read_lock_bh(&mode_lock); if (track_mode == CONN_MODE_NONE) goto out_unlock; if (in != track_dev || !is_our_packet(skb)) goto out_unlock; if (!need_auth_input(skb)) goto out_unlock; __refresh_keepalive_timer(); if (is_udp_packet(skb)) { /* * we need do nothing here */ read_unlock_bh(&mode_lock); return NF_ACCEPT; } hash = resolve_tcp_conn(skb); if (hash == NULL) goto out_unlock; todo = check_tcp_packet(skb, hash); if (todo & TODO_ADJUST_SEQ) (void)tcp_adjust_seq(skb, hash); conn_put(tuplehash_to_conn(hash));out_unlock: read_unlock_bh(&mode_lock); return NF_ACCEPT;}static unsigned int postroute_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){ struct tcp_tuplehash *hash; unsigned int todo; struct sk_buff *skb2; read_lock_bh(&mode_lock); if (track_mode == CONN_MODE_NONE) goto out_unlock; if (out != track_dev || !is_our_packet(skb)) goto out_unlock; if (!need_auth_output(skb)) goto out_unlock; __refresh_keepalive_timer(); if (is_udp_packet(skb)) { conn_do_udp(skb, okfn); read_unlock_bh(&mode_lock); return NF_STOLEN; } hash = resolve_tcp_conn(skb); if (hash == NULL) goto out_unlock; todo = check_tcp_packet(skb, hash); if (todo & TODO_SEND_ACK) { skb2 = build_ack_skb(skb); if (skb2 != NULL) okfn(skb2); } if (todo & TODO_SEND_AUTH) { skb2 = build_auth_skb(skb); if (skb2 != NULL) okfn(skb2); } if (todo & TODO_ADJUST_SEQ) (void)tcp_adjust_seq(skb, hash); conn_put(tuplehash_to_conn(hash));out_unlock: read_unlock_bh(&mode_lock); return NF_ACCEPT;}static struct nf_hook_ops preroute_hook_ops = { .hook = preroute_hook, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK_DEFRAG+1,};static struct nf_hook_ops postroute_hook_ops = { .hook = postroute_hook, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_LAST,};static void conn_hash_cleanup(void){ struct tcp_conn *conn; struct tcp_tuplehash *h; int i; /* free tcp_conn hash memory */i_see_dead_people: while (1) { conn = NULL; write_lock_bh(&hash_lock); for (i=0; i<TCP_CONN_HASH_SIZE; i++) { struct list_head *head = &tcp_conn_hash[i]; if (!list_empty(head)){ h = list_entry(head->next, struct tcp_tuplehash, list); conn = tuplehash_to_conn(h); conn_get(conn); break; } } write_unlock_bh(&hash_lock); if (conn == NULL) break; if (del_timer(&conn->timeout)) { death_by_timeout((unsigned long)conn); conn_put(conn); } } while (atomic_read(&tcp_conn_count) != 0) { schedule(); goto i_see_dead_people; }}static int conn_hooks_init(void){ int ret; ret = nf_register_hook(&preroute_hook_ops); if(ret < 0){ printk(KERN_ERR "PRE-ROUTE hook register failed\n"); goto out_err; } ret = nf_register_hook(&postroute_hook_ops); if(ret < 0){ printk(KERN_ERR "POST-ROUTE hook register failed\n"); goto out_unregister_1; } return 0;out_unregister_1: nf_unregister_hook(&preroute_hook_ops);out_err: return ret;}static void conn_hooks_cleanup(void){ nf_unregister_hook(&postroute_hook_ops); nf_unregister_hook(&preroute_hook_ops); synchronize_net();}static int conn_set_params(struct sock *sk, int optname, void *optval, unsigned int optlen){ struct conn_param cp; struct net_device *dev, *tmp_dev = NULL; struct e_address *e_addr=NULL, *tmp_addr; unsigned int e_len; int i; if (optlen < sizeof(struct conn_param)) return -EINVAL; if (copy_from_user(&cp, optval, sizeof(struct conn_param))) return -EFAULT; if (cp.e_count < 0) return -EINVAL; if (cp.e_count > 0) { e_len = cp.e_count * sizeof(struct e_address); if (optlen < sizeof(struct conn_param) + e_len) return -EINVAL; e_addr = kmalloc(e_len, GFP_KERNEL); if (e_addr == NULL) return -ENOMEM; if (copy_from_user(e_addr, optval+sizeof(struct conn_param), e_len)) { kfree(e_addr); return -EFAULT; } } dev = dev_get_by_name(&init_net, cp.devname); if (dev == NULL) { if (e_addr) kfree(e_addr); return -ENODEV; } write_lock_bh(&mode_lock); tmp_addr = conn_e_addr; conn_e_count = cp.e_count; if (conn_e_count != 0) { conn_e_addr = e_addr; for(i=0; i<conn_e_count; i++) conn_e_addr[i].addr &= conn_e_addr[i].mask; } tmp_dev = track_dev; track_dev = dev; write_unlock_bh(&mode_lock); if (tmp_addr) kfree(tmp_addr); if (tmp_dev) dev_put(tmp_dev); return 0;}static int conn_set_auth_cmd(struct sock *sk, int optname, void *optval, unsigned int optlen){ struct conn_auth_cmd cmd; int hash_todo = 0; if (optlen < sizeof(struct conn_auth_cmd)) return -EINVAL; if (copy_from_user(&cmd, optval, sizeof(struct conn_auth_cmd))) return -EFAULT; rtnl_lock(); write_lock_bh(&mode_lock); if (track_mode == CONN_MODE_NONE && cmd.cmd == CONN_MODE_AUTH) { track_mode = cmd.cmd; conn_pid = cmd.pid; conn_autologout = cmd.autologout; memcpy(conn_auth_data, cmd.auth_data, CONN_AUTH_DATA_LEN); hash_todo = 1; /* conn_hooks_init() */ } else if (track_mode == CONN_MODE_AUTH && cmd.cmd == CONN_MODE_NONE) { track_mode = cmd.cmd; conn_pid = 0; conn_autologout = 0; memset(conn_auth_data, 0, CONN_AUTH_DATA_LEN); hash_todo = 2; /* conn_hooks_cleanup */ } else { DEBUGP("Same Auth Cmd\n"); } write_unlock_bh(&mode_lock); if (hash_todo == 1) { init_keepalive_timer(); conn_hooks_init(); printk(KERN_INFO "Drcom-Kernel: Authentication Started.\n"); } else if (hash_todo == 2) { del_keepalive_timer(); conn_hooks_cleanup(); conn_hash_cleanup(); printk(KERN_INFO "Drcom-Kernel: Authentication Stopped.\n"); } rtnl_unlock(); return 0;}static int conn_set_sockopt(struct sock *sk, int optname, void *optval, unsigned int optlen){ switch (optname) { case CONN_SO_SET_PARAMS: /* set addresses of no need to auth */ return conn_set_params(sk, optname, optval, optlen); case CONN_SO_SET_AUTH_CMD: /* set auth data, and start auth */ return conn_set_auth_cmd(sk, optname, optval, optlen); default: return -ENOPROTOOPT; } return -ENOPROTOOPT;}static struct nf_sockopt_ops conn_so_ops = { .pf = PF_INET, .set_optmin = CONN_SO_BASE_CTL, .set_optmax = CONN_SO_SET_MAX+1, .set = &conn_set_sockopt, .owner = THIS_MODULE,};static int __init init(void){ int ret; int i; for (i=0; i<TCP_CONN_HASH_SIZE; i++) INIT_LIST_HEAD(&tcp_conn_hash[i]); ret = nf_register_sockopt(&conn_so_ops); if(ret != 0) return ret; printk(KERN_INFO "Drcom-Kernel " TCPTRACK_VERSION " module loaded\n"); return ret;}static void __exit fini(void){ int do_dirty_work=0; nf_unregister_sockopt(&conn_so_ops); rtnl_lock(); write_lock_bh(&mode_lock); if (track_mode == CONN_MODE_AUTH) do_dirty_work = 1; track_mode = CONN_MODE_NONE; write_unlock_bh(&mode_lock); if (do_dirty_work) { conn_hooks_cleanup(); conn_hash_cleanup(); } rtnl_unlock(); if (conn_e_addr) kfree(conn_e_addr); if (track_dev) dev_put(track_dev); printk(KERN_INFO "Drcom-Kernel " TCPTRACK_VERSION " module unloaded\n");}module_init(init);module_exit(fini);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -