add addmasqueraderule()
see issue #166 http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=1820 iptables -t nat -I POSTROUTING -o <extif> -s <iaddr> -p UDP --sport <iport> -j MASQUERADE --to-ports <eport>
This commit is contained in:
parent
f4324d45e5
commit
ba91c4ec23
|
@ -72,6 +72,12 @@ static int
|
|||
add_filter_rule(int proto, const char * rhost,
|
||||
const char * iaddr, unsigned short iport);
|
||||
|
||||
static int
|
||||
addmasqueraderule(int proto,
|
||||
unsigned short eport,
|
||||
const char * iaddr, unsigned short iport,
|
||||
const char * rhost, const char * extif);
|
||||
|
||||
static int
|
||||
addpeernatrule(int proto,
|
||||
const char * eaddr, unsigned short eport,
|
||||
|
@ -222,8 +228,13 @@ add_redirect_rule2(const char * ifname,
|
|||
UNUSED(ifname);
|
||||
|
||||
r = addnatrule(proto, eport, iaddr, iport, rhost);
|
||||
if(r >= 0)
|
||||
if(r >= 0) {
|
||||
add_redirect_desc(eport, proto, desc, timestamp);
|
||||
r = addmasqueraderule(proto, eport, iaddr, iport, rhost, ifname);
|
||||
if(r <= 0) {
|
||||
syslog(LOG_NOTICE, "add_redirect_rule2(): addmasqueraderule returned %d", r);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1003,6 +1014,29 @@ get_dscp_target(unsigned char dscp)
|
|||
return target;
|
||||
}
|
||||
|
||||
static struct ipt_entry_target *
|
||||
get_masquerade_target(unsigned short port)
|
||||
{
|
||||
struct ipt_entry_target * target;
|
||||
struct ip_nat_multi_range * mr;
|
||||
struct ip_nat_range * range;
|
||||
size_t size;
|
||||
|
||||
size = IPT_ALIGN(sizeof(struct ipt_entry_target))
|
||||
+ IPT_ALIGN(sizeof(struct ip_nat_multi_range));
|
||||
target = calloc(1, size);
|
||||
target->u.target_size = size;
|
||||
strncpy(target->u.user.name, "MASQUERADE", sizeof(target->u.user.name));
|
||||
/* one ip_nat_range already included in ip_nat_multi_range */
|
||||
mr = (struct ip_nat_multi_range *)&target->data[0];
|
||||
mr->rangesize = 1;
|
||||
range = &mr->range[0];
|
||||
range->min.tcp.port = range->max.tcp.port = htons(port);
|
||||
/*range->min.all = range->max.all = htons(port);*/
|
||||
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
|
||||
return target;
|
||||
}
|
||||
|
||||
/* iptc_init_verify_and_append()
|
||||
* return 0 on success, -1 on failure */
|
||||
static int
|
||||
|
@ -1134,6 +1168,80 @@ addnatrule(int proto, unsigned short eport,
|
|||
return r;
|
||||
}
|
||||
|
||||
/* for "Port Triggering"
|
||||
* Section 2.5.16 figure 2.2 in UPnP-gw-WANIPConnection-v2-Service.pdf
|
||||
* iptables -t nat -I POSTROUTING -o extif -s iaddr -p UDP --sport iport -j MASQUERADE --to-ports eport
|
||||
* iptables -t nat -A MINIUPNPD-PCP-PEER -o extif -s iaddr -p UDP --sport iport -j MASQUERADE --to-ports eport
|
||||
*/
|
||||
static int
|
||||
addmasqueraderule(int proto,
|
||||
unsigned short eport,
|
||||
const char * iaddr, unsigned short iport,
|
||||
const char * rhost, const char * extif)
|
||||
{
|
||||
int r = 0;
|
||||
struct ipt_entry * e;
|
||||
struct ipt_entry * tmp;
|
||||
struct ipt_entry_match *match = NULL;
|
||||
struct ipt_entry_target *target = NULL;
|
||||
|
||||
e = calloc(1, sizeof(struct ipt_entry));
|
||||
if(!e) {
|
||||
syslog(LOG_ERR, "%s: calloc(%d) error", "addmasqueraderule",
|
||||
(int)sizeof(struct ipt_entry));
|
||||
return -1;
|
||||
}
|
||||
e->ip.proto = proto;
|
||||
if(proto == IPPROTO_TCP) {
|
||||
match = get_tcp_match(0, iport);
|
||||
} else {
|
||||
match = get_udp_match(0, iport);
|
||||
}
|
||||
e->nfcache = NFC_IP_DST_PT;
|
||||
target = get_masquerade_target(eport);
|
||||
e->nfcache |= NFC_UNKNOWN;
|
||||
tmp = realloc(e, sizeof(struct ipt_entry)
|
||||
+ match->u.match_size
|
||||
+ target->u.target_size);
|
||||
if(!tmp) {
|
||||
syslog(LOG_ERR, "%s: realloc(%d) error", "addmasqueraderule",
|
||||
(int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size));
|
||||
free(e);
|
||||
free(match);
|
||||
free(target);
|
||||
return -1;
|
||||
}
|
||||
e = tmp;
|
||||
memcpy(e->elems, match, match->u.match_size);
|
||||
memcpy(e->elems + match->u.match_size, target, target->u.target_size);
|
||||
e->target_offset = sizeof(struct ipt_entry)
|
||||
+ match->u.match_size;
|
||||
e->next_offset = sizeof(struct ipt_entry)
|
||||
+ match->u.match_size
|
||||
+ target->u.target_size;
|
||||
if(extif != NULL) {
|
||||
strncpy(e->ip.outiface, extif, sizeof(e->ip.outiface));
|
||||
memset(e->ip.outiface_mask, 0xff, strlen(e->ip.outiface) + 1);/* Include nul-terminator in match */
|
||||
}
|
||||
/* internal host */
|
||||
if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*")))
|
||||
{
|
||||
e->ip.src.s_addr = inet_addr(iaddr);
|
||||
e->ip.smsk.s_addr = INADDR_NONE;
|
||||
}
|
||||
/* remote host */
|
||||
if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) {
|
||||
e->ip.dst.s_addr = inet_addr(rhost);
|
||||
e->ip.dmsk.s_addr = INADDR_NONE;
|
||||
}
|
||||
|
||||
r = iptc_init_verify_and_append("nat", miniupnpd_peer_chain, e, "addmasqueraderule");
|
||||
free(target);
|
||||
free(match);
|
||||
free(e);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* iptables -t nat -A MINIUPNPD-PCP-PEER -s iaddr -d rhost
|
||||
* -p proto --sport iport --dport rport -j SNAT
|
||||
* --to-source ext_ip:eport */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2012 Thomas Bernard
|
||||
* (c) 2006-2015 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
|||
#include <syslog.h>
|
||||
|
||||
#include "iptcrdr.c"
|
||||
#include "../commonrdr.h"
|
||||
/*#include "../commonrdr.h"*/
|
||||
|
||||
#ifndef PRIu64
|
||||
#define PRIu64 "llu"
|
||||
|
@ -22,7 +22,9 @@ main(int argc, char ** argv)
|
|||
{
|
||||
unsigned short eport, iport;
|
||||
const char * iaddr;
|
||||
printf("Usage %s <ext_port> <internal_ip> <internal_port>\n", argv[0]);
|
||||
int r;
|
||||
int proto = IPPROTO_TCP;
|
||||
printf("Usage %s <ext_port> <internal_ip> <internal_port> [TCP/UDP]\n", argv[0]);
|
||||
|
||||
if(argc<4)
|
||||
return -1;
|
||||
|
@ -30,11 +32,22 @@ main(int argc, char ** argv)
|
|||
eport = (unsigned short)atoi(argv[1]);
|
||||
iaddr = argv[2];
|
||||
iport = (unsigned short)atoi(argv[3]);
|
||||
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
|
||||
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport, NULL) < 0)
|
||||
if(argc >= 4) {
|
||||
if(strcasecmp(argv[4], "udp") == 0)
|
||||
proto = IPPROTO_UDP;
|
||||
}
|
||||
printf("trying to redirect port %hu to %s:%hu proto %d\n",
|
||||
eport, iaddr, iport, proto);
|
||||
if(addnatrule(proto, eport, iaddr, iport, NULL) < 0)
|
||||
return -1;
|
||||
if(add_filter_rule(IPPROTO_TCP, NULL, iaddr, iport) < 0)
|
||||
r = addmasqueraderule(proto, eport, iaddr, iport, NULL, "ppp0");
|
||||
syslog(LOG_DEBUG, "addmasqueraderule() returned %d", r);
|
||||
if(add_filter_rule(proto, NULL, iaddr, iport) < 0)
|
||||
return -1;
|
||||
if(proto == IPPROTO_UDP) {
|
||||
if(addpeernatrule(proto, "8.8.8.8"/*eaddr*/, eport, iaddr, iport, NULL, 0) < 0)
|
||||
fprintf(stderr, "addpeenatrule failed\n");
|
||||
}
|
||||
/* test */
|
||||
{
|
||||
unsigned short p1, p2;
|
||||
|
@ -63,8 +76,8 @@ main(int argc, char ** argv)
|
|||
}
|
||||
printf("trying to list nat rules :\n");
|
||||
list_redirect_rule(argv[1]);
|
||||
printf("deleting\n");
|
||||
delete_redirect_and_filter_rules(eport, IPPROTO_TCP);
|
||||
//printf("deleting\n");
|
||||
//delete_redirect_and_filter_rules(eport, proto);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue