首页 > 代码库 > 使用 libiptc 操作 iptables
使用 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
使用 libiptc 操作 iptables