使用 libiptc 操作 iptables
這些程式碼花了我三天才寫出來,filter表的操作沒問題,nat表操作不太對。在arm平臺也有點不對,懶得除錯了,分享出來吧。
#include <getopt.h> #include <sys/errno.h> #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <dlfcn.h> #include <time.h> #include <netdb.h> #include <libiptc/libiptc.h> //#include <ip_tables.h> #define MIN_PORT 0 #define MAX_PORT 65535 //linux/include/linux/netfilter_ipv4/ip_tables.h #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) struct xtc_handle *t_handle; void show_all_rule() { const char *chain = NULL; const char * policy = NULL; struct ipt_counters counter; for (chain = iptc_first_chain(t_handle); chain; chain = iptc_next_chain(t_handle)) { printf("\nChain: %s\n", chain); if (chain!=NULL && t_handle!=NULL) { policy = iptc_get_policy(chain,&counter,t_handle); printf("policy: %s\n",policy); printf(" packet count: %llu\t",counter.pcnt); printf(" byte count: %llu\n",counter.bcnt); } else printf("policy error !\n"); x_get_rule(chain,t_handle); }//for } //append rule int x_append_rule(char *chain ,struct ipt_entry *e) { if (iptc_append_entry(chain,e,t_handle)!=1) { printf("Error x_append_rule: %s\n", iptc_strerror(errno)); return 0; } iptc_commit(t_handle); return 1; } //insert tule by num int x_insert_rule(char *chain ,struct ipt_entry *e,int num) { if (iptc_insert_entry(chain,e,num,t_handle)!=1) { printf("Error x_insert_rule: %s\n", iptc_strerror(errno)); return 0; } iptc_commit(t_handle); return 1; } //iptables -I OUTPUT -s 192.168.6.2 -d 192.168.3.4 -p UDP --dport 1933 -j DROP int demo_insert() { struct ipt_entry_target *a_t ; struct ipt_entry_match *a_m; struct ipt_entry *a_e; struct ipt_tcp *ptcp; struct ipt_ip *pip; size_t target_size,match_size,entry_size; //init size match_size = sizeof(struct ipt_entry_match) + sizeof(struct ipt_tcp); target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_size = sizeof(*a_e) + target_size + match_size; //full struct ipt_entry a_e = malloc(entry_size); memset(a_e,0,entry_size); a_e->ip.src.s_addr = inet_addr("192.168.6.2"); a_e->ip.smsk.s_addr = -1; //--- for --to--destination a_e->ip.dst.s_addr = inet_addr("192.168.3.4"); a_e->ip.dmsk.s_addr = -1; //--- a_e->ip.proto = 17;//udp a_e->target_offset = sizeof(*a_e) + match_size; a_e->next_offset = entry_size; //full struct ip_entry_match a_m = (struct ipt_entry_match*)a_e->elems; a_m->u.user.match_size = match_size; strcpy(a_m->u.user.name,"udp"); //full struct ipt_tcp ptcp = (struct ipt_tcp*)a_m->data; ptcp->spts[0] = -1;ptcp->spts[1] = -1;//any sport ptcp->dpts[0] = 1933;ptcp->dpts[1] = 1933;//one port //full struct ipt_entry_target a_t = (struct ipt_entry_target*)(a_e->elems + match_size); a_t->u.user.target_size = target_size; strcpy(a_t->u.user.name,"DROP"); //do_command x_insert_rule("OUTPUT",a_e,0);//num==1 can‘t add ?? return 1; } //get chain and policy list void x_get_rule(const char *chain,struct xtc_handle *handle) { const struct ipt_entry* rule; struct ipt_entry_match* a_m; struct ipt_tcp* ptcp; for(rule = iptc_first_rule(chain,handle); rule; rule = iptc_next_rule(rule,handle)) { const char *target = NULL; target= iptc_get_target(rule,handle); //printf("rule name : %s\n",target); //printf("rule count: %llu\n",rule->counters.pcnt); //printf("rule strlen:%llu\n",rule->counters.bcnt); struct protoent *pro = NULL; pro= getprotobynumber(rule->ip.proto); if(pro != NULL ) { printf(" policy_id:%04d proto_name:%s \n",pro->p_proto, pro->p_name); } printf(" in_iface: "); if(rule->ip.iniface[0] == ‘\0‘ )// -i param printf("any\t"); else printf("%s\t",rule->ip.iniface); printf(" out_iface: "); if(rule->ip.outiface[0] == ‘\0‘ )//-o param printf("any\n"); else printf("%s\n",rule->ip.outiface); char addr[32] = {0}; printf(" sip:%s/%s \t",inet_ntop(AF_INET,&(rule->ip.src),addr,sizeof(addr)),inet_ntop(AF_INET,&(rule->ip.smsk),addr,sizeof(addr)) ); printf("dip:%s/%s\n",inet_ntop(AF_INET,&(rule->ip.dst),addr,sizeof(addr)),inet_ntop(AF_INET,&(rule->ip.dmsk),addr,sizeof(addr)) ); //ip.dmsk.s_addr //full struct ip_entry_match a_m = (struct ipt_entry_match*)rule->elems; //full struct ipt_tcp ptcp = (struct ipt_tcp*)a_m->data; if (ptcp->spts[0]<=0 || ptcp->spts[0]==0xffff) printf(" sport : any \t"); else printf(" sport range : %d --- %d \t",ptcp->spts[0],ptcp->spts[1]); if (ptcp->dpts[0]<=0 || ptcp->dpts[0]==0xffff) printf("d_port : any \t"); else printf("d_port range : %d --- %d \n",ptcp->dpts[0],ptcp->dpts[1]); } } //init libiptc int x_init(int type) { //if "-t nat" tablename == "nat" ,it table can use PREROUTING const char *default_tablename = "filter"; const char *nat_tablename = "nat"; const char *chain = NULL; if (type==1) { t_handle = iptc_init(default_tablename); printf("***** oepn nat table *****\n"); } else { printf("***** open nat table *****\n"); t_handle = iptc_init(nat_tablename); } if ( t_handle == NULL ) { printf("Error initializing: %s\n", iptc_strerror(errno)); return errno; } //del nat table all rule for (chain = iptc_first_chain(t_handle); chain; chain = iptc_next_chain(t_handle)) { iptc_flush_entries(chain,t_handle); printf("Clean %s rule \n",chain); }//for return 1; } //--------------------------------------------------------------- //iptables -A INPUT -i eth0 -p icmp -j DROP int demo_append1() { //***append route struct ipt_entry_target *a_t = NULL; struct ipt_entry *a_e ; int i; size_t target_size,entry_size; //init size target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_size = sizeof(*a_e) + target_size; //full ipt_entry a_e = malloc(entry_size); memset(a_e,0,entry_size); strcpy(a_e->ip.iniface,"eth0"); //a_e->ip.iniface[0] == ‘\0‘ for(i=0;i<(strlen("eth0")+1);i++) a_e->ip.iniface_mask[i] = 0xffff; a_e->ip.proto = 1; //icmp a_e->target_offset = sizeof(*a_e); a_e->next_offset = entry_size; //full ipt_entry_target a_t = (struct ipt_entry_target *)a_e->elems; a_t->u.user.target_size = target_size; strcpy(a_t->u.user.name,"DROP"); //do_command x_append_rule("INPUT",a_e); return 1; } /* 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 }; struct ipt_ip { struct in_addr src, dst; struct in_addr smsk, dmsk; char iniface[IFNAMSIZ], outiface[IFNAMSIZ]; unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ]; u_int16_t proto; u_int8_t flags; u_int8_t invflags; }; */ //iptables -A FORWARD -s 192.168.2.2 -d 192.168.3.4 -p tcp --dport 80 -j ACCEPT int demo_append2() { struct ipt_entry_target *a_t ; struct ipt_entry_match *a_m; struct ipt_entry *a_e; struct ipt_tcp *ptcp; struct ipt_ip *pip; size_t target_size,match_size,entry_size; //init size match_size = sizeof(struct ipt_entry_match) + sizeof(struct ipt_tcp); target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_size = sizeof(*a_e) + target_size + match_size; //full struct ipt_entry a_e = malloc(entry_size); memset(a_e,0,entry_size); a_e->ip.src.s_addr = inet_addr("192.168.2.2"); a_e->ip.smsk.s_addr = -1; a_e->ip.dst.s_addr = inet_addr("192.168.3.4"); a_e->ip.dmsk.s_addr = -1; a_e->ip.proto = 6;//tcp a_e->target_offset = sizeof(*a_e) + match_size; a_e->next_offset = entry_size; //full struct ip_entry_match a_m = (struct ipt_entry_match*)a_e->elems; a_m->u.user.match_size = match_size; strcpy(a_m->u.user.name,"tcp"); //full struct ipt_tcp ptcp = (struct ipt_tcp*)a_m->data; ptcp->spts[0] = -1;ptcp->spts[1] = -1;//any sport ptcp->dpts[0] = 80;ptcp->dpts[1] = 80;//one port //full struct ipt_entry_target a_t = (struct ipt_entry_target*)(a_e->elems + match_size); a_t->u.user.target_size = target_size; strcpy(a_t->u.user.name,"ACCEPT"); //do_command x_append_rule("FORWARD",a_e); return 1; } //iptables -A PREROUTING -d 0.0.0.0/0 -p tcp --dport 80 -j DNAT --to--destination 172.16.1.1 void demo_do_nat() { struct ipt_entry_target *a_t ; struct ipt_entry_match *a_m; struct ipt_entry *a_e; struct ipt_tcp *ptcp; struct ipt_ip *pip; size_t target_size,match_size,entry_size; //init size match_size = sizeof(struct ipt_entry_match) + sizeof(struct ipt_tcp); target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_size = sizeof(*a_e) + target_size + match_size; //full struct ipt_entry a_e = malloc(entry_size); memset(a_e,0,entry_size); a_e->ip.src.s_addr = 0; a_e->ip.dmsk.s_addr = -1; a_e->ip.dst.s_addr = 0; a_e->ip.dmsk.s_addr = -1; a_e->ip.proto = 6;//tcp a_e->target_offset = sizeof(*a_e) + match_size; a_e->next_offset = entry_size; //full struct ip_entry_match a_m = (struct ipt_entry_match*)a_e->elems; a_m->u.user.match_size = match_size; strcpy(a_m->u.user.name,"tcp"); //full struct ipt_tcp ptcp = (struct ipt_tcp*)a_m->data; ptcp->spts[0] = -1;ptcp->spts[1] = -1;//any sport ptcp->dpts[0] = 80;ptcp->dpts[1] = 80;//one port //full struct ipt_entry_target a_t = (struct ipt_entry_target*)(a_e->elems + match_size); a_t->u.user.target_size = target_size; strcpy(a_t->u.user.name,"DNAT"); //do_command x_append_rule("PREROUTING",a_e); } //opt nat table void do_nat_table() { //open nat table if (x_init(2)!=1) { exit(0); } //iptables //iptables -t nat -A PREROUTING -d 0.0.0.0/0 -p tcp --dport 80 -j DNAT --to--destination 172.16.1.1 demo_do_nat();//.... //show all nat table rule printf("****************************************\n"); printf("SHOW ALL NAT TABLE RULE \n"); printf("****************************************\n"); show_all_rule(); } //opt to filter table void do_filter_table() { //open filter table if (x_init(1)!=1) { exit(0); } //iptables -A INPUT -i eth0 -p icmp -j DROP demo_append1(); //iptables -A FORWARD -s 192.168.2.2 -d 192.168.3.4 -p tcp --dport 80 -j DROP demo_append2(); //iptables -I OUTPUT 1 -s 192.168.6.2 -d 192.168.3.4 -p UDP --dport 1933 -j DROP demo_insert(); //show all filter table rule printf("****************************************\n"); printf("SHOW ALL FILTER TABLE RULE \n"); printf("****************************************\n"); show_all_rule(); } int main(void) { //use default table filter to : iptc_append_entry() iptc_insert_entry() //note filter talbe can use policy is FORWARD,INPUT ,OUTPUT do_filter_table(); //user table nat to : iptc_append_entry() //note -DNAT only can use in nat talbe,and policy == PREROUTING and OUTPUT do_nat_table(); exit(0); } /* main */
執行結果:
***** oepn nat table ***** Clean INPUT rule Clean FORWARD rule Clean OUTPUT rule **************************************** SHOW ALL FILTER TABLE RULE **************************************** Chain: INPUT policy: ACCEPT packet count: 821 byte count: 83028 policy_id:0001 proto_name:icmp in_iface: eth0 out_iface: any sip:0.0.0.0/0.0.0.0 dip:0.0.0.0/0.0.0.0 sport : any d_port range : 17 --- 0 Chain: FORWARD policy: ACCEPT packet count: 0 byte count: 0 policy_id:0006 proto_name:tcp in_iface: any out_iface: any sip:192.168.2.2/192.168.2.2 dip:192.168.3.4/192.168.3.4 sport : any d_port range : 80 --- 80 Chain: OUTPUT policy: ACCEPT packet count: 282 byte count: 46662 policy_id:0017 proto_name:udp in_iface: any out_iface: any sip:192.168.6.2/192.168.6.2 dip:192.168.3.4/192.168.3.4 sport : any d_port range : 1933 --- 1933 ***** open nat table ***** Clean PREROUTING rule Clean INPUT rule Clean OUTPUT rule Clean POSTROUTING rule **************************************** SHOW ALL NAT TABLE RULE **************************************** Chain: PREROUTING policy: ACCEPT packet count: 7334 byte count: 384511 policy_id:0006 proto_name:tcp in_iface: any out_iface: any sip:0.0.0.0/0.0.0.0 dip:0.0.0.0/0.0.0.0 sport : any d_port range : 80 --- 80 Chain: INPUT policy: ACCEPT packet count: 698 byte count: 105695 Chain: OUTPUT policy: ACCEPT packet count: 714 byte count: 40988 Chain: POSTROUTING policy: ACCEPT packet count: 714 byte count: 40988
轉之原文:http://blog.csdn.net/xjb2001/article/details/39579227