2016-06-07 9 views
0

Ich versuche, ein c-Programm zu erstellen, Port-Weiterleitungsregel mit libiptc zu erstellen.libiptc: DNAT-Regel mit Ziel-IP hinzufügen

static int insert_forward_rule(const char *table, const char *chain, unsigned int src, unsigned int dest, const char * ports, const char *target1, char * proto) { 
struct xtc_handle *h; 
struct ipt_entry *en = NULL; 
struct ipt_entry * e; 

struct ipt_entry_match * match_proto, * match_limit; 
struct ipt_entry_target * target; 
unsigned int size_ipt_entry, size_ipt_entry_match, size_ipt_entry_target, total_length; 

size_ipt_entry = IPT_ALIGN(sizeof (struct ipt_entry)); 
size_ipt_entry_match = IPT_ALIGN(sizeof (struct ipt_entry_match)) + sizeof (struct ipt_tcp) + sizeof (int); 
size_ipt_entry_target = IPT_ALIGN(sizeof (struct ipt_entry_target) + sizeof (IPTC_LABEL_ACCEPT)); 
total_length = 216; //size_ipt_entry + size_ipt_entry_match + size_ipt_entry_target + IPT_ALIGN(sizeof (struct ipt_natinfo)); //size_ipt_entry + 48 + 40 
//printf("size of ipt ebtry=%u,match=%u,target=%u,total=%u\n", size_ipt_entry, size_ipt_entry_match, size_ipt_entry_target, total_length); 
//memory allocation for all structs that represent the netfilter rule we want to insert 

e = calloc(1, total_length); 
if (e == NULL) { 
    printf("malloc failure"); 
    exit(1); 
} 
int size = 160; 
//offsets to the other bits: 
//target struct begining 
e->target_offset = size; //size_ipt_entry + size_ipt_entry_match; //+ size_ipt_tcp + size_rateinfo + size_physdevinfo; 
//next "e" struct, end of the current one 
e->next_offset = total_length; 
e->nfcache = NFC_IP_DST_PT; 

if (dest) { 
    e->ip.dst.s_addr = dest; 
    e->ip.dmsk.s_addr = 0xFFFFFFFF; 

} 
match_limit = (struct ipt_entry_match *) (e->elems); //+ match_proto->u.match_size 
match_limit->u.user.match_size = size_ipt_entry_match; //size_ipt_entry_match*3; //+ size_rateinfo; 
strncpy(match_limit->u.user.name, "tcp", sizeof (match_limit->u.user.name)); //set name of the module, we will use in this match 
struct ipt_tcp *info = (struct ipt_tcp *) match_limit->data; 
unsigned int i = 0; 
if (strchr(ports, ':') != NULL) { 
    char aPort[2][10]; 
    sscanf(ports, "%[^:], %[^:]", aPort[0], aPort[1]); 

    info->dpts[0] = atoi(aPort[0]); 
    info->dpts[1] = atoi(aPort[1]); 
} else { 
    info->dpts[0] = info->dpts[1] = atoi(ports); 

} 
info->spts[0] = 0; 
info->spts[1] = 0xFFFF; 
e->ip.proto = IPPROTO_TCP; 
printf("Target offset=%d,next offset=%d\n", e->target_offset, e->next_offset); 
target = (struct ipt_entry_target *) ((void*) e + e->target_offset); // + size_ipt_entry_match); //+ size_ipt_tcp + size_rateinfo + size_physdevinfo 
size = 56; 
target->u.user.target_size = size_ipt_entry_target + IPT_ALIGN(sizeof (struct nf_nat_range)); // size_ipt_entry_target; 
target->u.user.revision = 0; 
strncpy(target->u.user.name, target1, sizeof (target->u.user.name)); 
struct ipt_natinfo *inf = (struct ipt_natinfo*) target->data; 
struct nf_nat_range range; 
memset(&range, 0, sizeof (range)); 
range.flags |= IP_NAT_RANGE_MAP_IPS; 
range.min_ip = range.max_ip = src; 
inf->mr.rangesize++; 
inf->mr.range[inf->mr.rangesize] = range; 
inf->t.u.target_size = XT_ALIGN(sizeof (*inf) + inf->mr.rangesize * sizeof (struct nf_nat_range)); 


printf("after s_addr\n\n"); 


//All the functions, mentioned below could be found in "Querying libiptc HOWTO" manual 
h = iptc_init(table); 
printf("h=%d\n", h); 
if (!h) { 
    printf("Error initializing: %s\n", iptc_strerror(errno)); 
    return 0; 
} 

printf("target_size=%d,match=%d,chain=%s,table=%s,target=%s\n", target->u.user.target_size, match_limit->u.user.match_size, chain, table, target1); 

int x = iptc_append_entry(chain, e, h); 
if (!x) { 
    printf("Error append_entry: %s\n", iptc_strerror(errno)); 
    goto ERROR; 
} 
printf("%d,chain=%s,target=%s\n", target->u.user.target_size, chain, table); 
int y = iptc_commit(h); 
if (!y) { 
    printf("Error no=%d,commit: %s\n", errno, iptc_strerror(errno)); 
    goto ERROR; 
} 
iptc_free(h); 
if (e != NULL) { 
    free(e); 
    e = NULL; 
} 
return 1; 
ERROR: 
iptc_free(h); 
if (e != NULL) { 
    free(e); 
    e = NULL; 
} 
return 0; 
} 

diese Funktion

inet_pton(AF_INET, "20.10.10.254", &a); 
inet_pton(AF_INET, "20.10.10.100", &b); 
insert_forward_rule("nat", "port_forward", b, a, "1111", "DNAT", "tcp"); 

Jedes Mal, wenn ich diesen Code ausführen zu nennen, i Fehler als ungültige Argumente sind immer (Code 22) .Wenn ich die Position von rangesize auf unter iptc_init ändern() dann gab einen Fehlercode 94 (Socket-Operation auf Nicht-Socket) Ich versuchte struct nf_nat_range Struktur direkt, aber dann speichert es nicht die Ziel-IP in Regeln, anstatt dass seine zeigt zufällig. Regel, die ich machen möchte, ist

iptables -t nat -A port_forward -j DNAT -d 192.168.10.202 -p udp --dport 8080:8084 --to 20.10.10.112 

, was es mit der Struktur nf_nat_range schafft wird

Chain port_forward (0 references) 
pkts  bytes target  prot opt in  out  source    destination   
    0  0 DNAT  tcp -- *  *  0.0.0.0/0   20.10.10.254  tcp dpt:1111 to: random 
    0  0 DNAT  tcp -- *  *  0.0.0.0/0   20.10.10.254  tcp dpt:1111 to: random 
    0  0 DNAT  tcp -- *  *  0.0.0.0/0   20.10.10.254  tcp dpt:1111 to: random 

Antwort

0

Dies sind die Funktionen, die mir geholfen zu DNAT und SNAT Regeln libiptc hinzufügen oder löschen. Ich habe dies auf mein Konto GitHub hochgeladen.

void iptc_add_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) { 
iptc_handle_t handle; 
struct ipt_entry *chain_entry; 
struct ipt_entry_match *entry_match = NULL; 
struct ipt_entry_target *entry_target; 
ipt_chainlabel labelit; 
long match_size; 
int result = 0; 

chain_entry = (struct ipt_entry *) calloc(1, sizeof (*chain_entry)); 

if (src) { 
    chain_entry->ip.src.s_addr = inet_addr(src); 
    chain_entry->ip.smsk.s_addr = inet_addr("255.255.255.255"); 
} 
if (dest) { 
    chain_entry->ip.dst.s_addr = inet_addr(dest); 
    chain_entry->ip.dmsk.s_addr = inet_addr("255.255.255.255"); 
} 

if (iniface) strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ); 
if (outiface) strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ); 

if (strcmp(protocol, "TCP") == 0) { 
    chain_entry->ip.proto = IPPROTO_TCP; 
    entry_match = get_tcp_match(srcports, destports, &chain_entry->nfcache); 
} else if (strcmp(protocol, "UDP") == 0) { 
    chain_entry->ip.proto = IPPROTO_UDP; 
    entry_match = get_udp_match(srcports, destports, &chain_entry->nfcache); 
} else { 
    printf("Unsupported protocol: %s", protocol); 
    return; 
} 

if (strcmp(target, "") == 0 
     || strcmp(target, IPTC_LABEL_ACCEPT) == 0 
     || strcmp(target, IPTC_LABEL_DROP) == 0 
     || strcmp(target, IPTC_LABEL_QUEUE) == 0 
     || strcmp(target, IPTC_LABEL_RETURN) == 0) { 
    size_t size; 

    size = IPT_ALIGN(sizeof (struct ipt_entry_target)) + IPT_ALIGN(sizeof (int)); 
    entry_target = (struct ipt_entry_target *) calloc(1, size); 
    entry_target->u.user.target_size = size; 
    strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN); 
} else if (strcmp(target, "DNAT") == 0) { 
    entry_target = get_dnat_target(dnat_to, &chain_entry->nfcache); 
    printf("dnat\n"); 
} else if (strcmp(target, "SNAT") == 0) { 
    entry_target = get_snat_target(dnat_to, &chain_entry->nfcache); 
    printf("snat\n"); 
} 

if (entry_match) 
    match_size = entry_match->u.match_size; 
else 
    match_size = 0; 
struct ipt_entry *tmp_ipt = chain_entry; 
chain_entry = (struct ipt_entry *) realloc(chain_entry, sizeof (*chain_entry) + match_size + entry_target->u.target_size); 
if (chain_entry == NULL) { 
    free(tmp_ipt); 
} 
memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size); 
chain_entry->target_offset = sizeof (*chain_entry) + match_size; 
chain_entry->next_offset = sizeof (*chain_entry) + match_size + entry_target->u.target_size; 
printf("target->offset=%d,next_offset=%d,target_size=%d\n", chain_entry->target_offset, chain_entry->next_offset, entry_target->u.user.target_size); 
if (entry_match) { 
    memcpy(chain_entry->elems, entry_match, match_size); 
    printf("%d\n", __LINE__); 
} 
printf("%d\n", __LINE__); 
handle = iptc_init(table); 
if (!handle) { 
    printf("libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno)); 
    free(chain_entry); 
    free(entry_target); 
    if (entry_match) free(entry_match); 
    return; 
} 

strncpy(labelit, chain, sizeof (ipt_chainlabel)); 
printf("%d\n", __LINE__); 
result = iptc_is_chain(chain, handle); 
if (!result) { 
    printf("libiptc error: Chain %s does not exist!", chain); 
    free(chain_entry); 
    free(entry_target); 
    if (entry_match) free(entry_match); 
    return; 
} 
printf("%d,labeit=%s\n", __LINE__, labelit); 
if (append) 
    result = iptc_append_entry(labelit, chain_entry, handle); 
else 
    result = iptc_insert_entry(labelit, chain_entry, 0, handle); 
printf("%d\n", __LINE__); 
if (!result) { 
    printf("libiptc error: Can't add, %s", iptc_strerror(errno)); 
    free(chain_entry); 
    free(entry_target); 
    if (entry_match) free(entry_match); 
    return; 
} 
printf("%d\n", __LINE__); 
result = iptc_commit(handle); 
if (!result) { 
    printf("libiptc error: Commit error, %s", iptc_strerror(errno)); 
    free(chain_entry); 
    free(entry_target); 
    if (entry_match) free(entry_match); 
    return; 
} else 
    printf("added new rule to block successfully"); 

if (entry_match) free(entry_match); 
free(entry_target); 
free(chain_entry); 

}

void iptc_delete_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to) { 
iptc_handle_t handle; 
const struct ipt_entry *e; 
ipt_chainlabel labelit; 
int i, result; 
unsigned long int s_src, s_dest; 

if (src) s_src = inet_addr(src); 
if (dest) s_dest = inet_addr(dest); 

handle = iptc_init(table); 
if (!handle) { 
    printf("libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno)); 
    return; 
} 

strncpy(labelit, chain, sizeof (ipt_chainlabel)); 
result = iptc_is_chain(chain, handle); 
if (!result) { 
    printf("libiptc error: Chain %s does not exist!", chain); 
    return; 
} 
for (e = iptc_first_rule(chain, handle), i = 0; e; e = iptc_next_rule(e, handle), i++) { 
    if (src && e->ip.src.s_addr != s_src) continue; 
    else if (dest && e->ip.dst.s_addr != s_dest) continue; 
    else if (iniface && strcmp(e->ip.iniface, iniface) != 0) continue; 
    else if (outiface && strcmp(e->ip.outiface, outiface) != 0) continue; 
    else if (protocol && strcmp(protocol, "TCP") == 0 && e->ip.proto != IPPROTO_TCP) continue; 
    else if (protocol && strcmp(protocol, "UDP") == 0 && e->ip.proto != IPPROTO_UDP) continue; 
    else if ((srcports || destports) && IPT_MATCH_ITERATE_MY(e, matchcmp, srcports, destports) == 0) continue; 
    else if (target && strcmp(target, iptc_get_target(e, handle)) != 0) continue; 
    else if (dnat_to && strcmp(target, "DNAT") == 0) { 
     struct ipt_entry_target *t; 
     struct ip_nat_multi_range *mr; 
     struct ip_nat_range *r, range; 

     t = (struct ipt_entry_target *) (e + e->target_offset); 
     mr = (struct ip_nat_multi_range *) ((void *) &t->data); 

     if (mr->rangesize != 1) continue; // we have only single dnat_to target now 
     r = mr->range; 
     parse_range(dnat_to, &range); 
     if (r->flags == range.flags 
       && r->min_ip == range.min_ip 
       && r->max_ip == range.max_ip 
       && r->min.all == range.min.all 
       && r->max.all == range.max.all) { 
      break; 
     } 
    } else break; 
} 
if (!e) return; 
result = iptc_delete_num_entry(chain, i, handle); 
if (!result) { 
    printf("libiptc error: Delete error, %s", iptc_strerror(errno)); 
    return; 
} 
result = iptc_commit(handle); 
if (!result) { 
    printf("libiptc error: Commit error, %s", iptc_strerror(errno)); 
    return; 
} else 
    printf("deleted rule from block successfully"); 

}

int matchcmp(const struct ipt_entry_match *match, const char *srcports, const char *destports) { 
u_int16_t temp[2]; 

if (strcmp(match->u.user.name, "tcp") == 0) { 
    struct ipt_tcp *tcpinfo = (struct ipt_tcp *) match->data; 

    if (srcports) { 
     parse_ports(srcports, temp); 
     if (temp[0] != tcpinfo->spts[0] || temp[1] != tcpinfo->spts[1]) return 0; 
    } 
    if (destports) { 
     parse_ports(destports, temp); 
     if (temp[0] != tcpinfo->dpts[0] || temp[1] != tcpinfo->dpts[1]) return 0; 
    } 
    return 1; 
} else if (strcmp(match->u.user.name, "udp") == 0) { 
    struct ipt_udp *udpinfo = (struct ipt_udp *) match->data; 

    if (srcports) { 
     parse_ports(srcports, temp); 
     if (temp[0] != udpinfo->spts[0] || temp[1] != udpinfo->spts[1]) return 0; 
    } 
    if (destports) { 
     parse_ports(destports, temp); 
     if (temp[0] != udpinfo->dpts[0] || temp[1] != udpinfo->dpts[1]) return 0; 
    } 
    return 1; 
} else return 0; 

}

/* Diese Funktionen dienen structs */

struct ipt_entry_match *get_tcp_match(const char *sports, const char *dports, unsigned int *nfcache) { 
struct ipt_entry_match *match; 
struct ipt_tcp *tcpinfo; 
size_t size; 

size = IPT_ALIGN(sizeof (*match)) + IPT_ALIGN(sizeof (*tcpinfo)); 
match = (struct ipt_entry_match *) calloc(1, size); 
match->u.match_size = size; 
strncpy(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN); 

tcpinfo = (struct ipt_tcp *) match->data; 
tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF; 
printf("sports=%s,dports=%s\n", sports, dports); 
if (sports) { 
    *nfcache |= NFC_IP_SRC_PT; 
    parse_ports(sports, tcpinfo->spts); 
    printf("%d\n", __LINE__); 
} 
if (dports) { 
    *nfcache |= NFC_IP_DST_PT; 
    parse_ports(dports, tcpinfo->dpts); 
    printf("%d\n", __LINE__); 
} 

return match; 
zu erstellen

}

struct ipt_entry_match *get_udp_match(const char *sports, const char *dports, unsigned int *nfcache) { 
struct ipt_entry_match *match; 
struct ipt_udp *udpinfo; 
size_t size; 

size = IPT_ALIGN(sizeof (*match)) + IPT_ALIGN(sizeof (*udpinfo)); 
match = (struct ipt_entry_match *) calloc(1, size); 
match->u.match_size = size; 
strncpy(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN); 

udpinfo = (struct ipt_udp *) match->data; 
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF; 
printf("sports=%s,dports=%s\n", sports, dports); 
if (sports) { 
    *nfcache |= NFC_IP_SRC_PT; 
    parse_ports(sports, udpinfo->spts); 
    printf("%d\n", __LINE__); 
} 
if (dports) { 
    *nfcache |= NFC_IP_DST_PT; 
    parse_ports(dports, udpinfo->dpts); 
    printf("%d\n", __LINE__); 
} 

return match; 

}

struct ipt_entry_target *get_dnat_target(const char *input, unsigned int *nfcache) { 
struct ipt_entry_target *target; 
struct ipt_natinfo *info; 
struct ip_nat_range range; 

char *buffer; 
size_t size; 

/* Can't cache this */ 
*nfcache |= NFC_UNKNOWN; 

buffer = strdup(input); 
size = IPT_ALIGN(sizeof (*target)) + IPT_ALIGN(sizeof (struct ip_nat_multi_range)); 
target = (struct ipt_entry_target *) calloc(1, size); 
target->u.target_size = size; 
strncpy(target->u.user.name, "DNAT", IPT_FUNCTION_MAXNAMELEN); 

info = (struct ipt_natinfo *) target; 
printf("buffer range=%s\n", buffer); 
parse_range(buffer, &range); 
target = &(append_range(info, &range)->t); 
printf("range=%d\n", range.flags); 
printf("%d\n", __LINE__); 
free(buffer); 

return target; 

}

struct ipt_entry_target *get_snat_target(const char *input, unsigned int *nfcache) { 
struct ipt_entry_target *target; 
struct ipt_natinfo *info; 
struct ip_nat_range range; 

char *buffer; 
size_t size; 

/* Can't cache this */ 
*nfcache |= NFC_UNKNOWN; 

buffer = strdup(input); 
size = IPT_ALIGN(sizeof (*target)) + IPT_ALIGN(sizeof (struct ip_nat_multi_range)); 
target = (struct ipt_entry_target *) calloc(1, size); 
target->u.target_size = size; 
strncpy(target->u.user.name, "SNAT", IPT_FUNCTION_MAXNAMELEN); 

info = (struct ipt_natinfo *) target; 
printf("buffer range=%s\n", buffer); 
parse_range(buffer, &range); 
target = &(append_range(info, &range)->t); 
printf("range=%d\n", range.flags); 
printf("%d\n", __LINE__); 
free(buffer); 

return target; 

}

/* kopiert und modifiziert von libipt_tcp.c und libipt_udp.c */

static u_int16_t parse_port(const char *port) { 
unsigned int portnum; 

if ((portnum = service_to_port(port)) != -1) { 
    return (u_int16_t) portnum; 
} else { 
    return atoi(port); 
} 
}

static void parse_ports(const char *portstring, u_int16_t *ports) { 
char *buffer; 
char *cp; 

buffer = strdup(portstring); 
if ((cp = strchr(buffer, ':')) == NULL) 
    ports[0] = ports[1] = parse_port(buffer); 
else { 
    *cp = '\0'; 
    cp++; 

    ports[0] = buffer[0] ? parse_port(buffer) : 0; 
    ports[1] = cp[0] ? parse_port(cp) : 0xFFFF; 
} 
free(buffer); 

}

static int service_to_port(const char *name) { 
struct servent *service; 

if ((service = getservbyname(name, "tcp")) != NULL) 
    return ntohs((unsigned short) service->s_port); 

return -1; 

}

/* kopiert und modifiziert von libipt_DNAT.c */

static void parse_range(const char *input, struct ip_nat_range *range) { 
char *colon, *dash, *buffer; 
in_addr_t ip; 

buffer = strdup(input); 
memset(range, 0, sizeof (*range)); 
colon = strchr(buffer, ':'); 

if (colon) { 
    int port; 

    range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 

    port = atoi(colon + 1); 
    dash = strchr(colon, '-'); 
    if (!dash) { 
     range->min.all 
       = range->max.all 
       = htons(port); 
    } else { 
     int maxport; 

     maxport = atoi(dash + 1); 
     range->min.all = htons(port); 
     range->max.all = htons(maxport); 
    } 
    /* Starts with a colon? No IP info...*/ 
    if (colon == buffer) { 
     free(buffer); 
     return; 
    } 
    *colon = '\0'; 
} 

range->flags |= IP_NAT_RANGE_MAP_IPS; 
dash = strchr(buffer, '-'); 
if (colon && dash && dash > colon) 
    dash = NULL; 

if (dash) 
    *dash = '\0'; 

ip = inet_addr(buffer); 
range->min_ip = ip; 
if (dash) { 
    ip = inet_addr(dash + 1); 
    range->max_ip = ip; 
} else 
    range->max_ip = range->min_ip; 

free(buffer); 
return; 

}
static struct ipt_natinfo *append_range(struct ipt_natinfo *info, const struct ip_nat_range *range) { 
unsigned int size; 

/* One ip_nat_range already included in ip_nat_multi_range */ 
size = IPT_ALIGN(sizeof (*info) + info->mr.rangesize * sizeof (*range)); 

info = (struct ipt_natinfo *) realloc(info, size); 

info->t.u.target_size = size; 
info->mr.range[info->mr.rangesize] = *range; 
info->mr.rangesize++; 
printf("range size=%d\n", info->mr.rangesize); 
return info; 

}