首页 > 代码库 > 使用 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