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,
|
add_filter_rule(int proto, const char * rhost,
|
||||||
const char * iaddr, unsigned short iport);
|
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
|
static int
|
||||||
addpeernatrule(int proto,
|
addpeernatrule(int proto,
|
||||||
const char * eaddr, unsigned short eport,
|
const char * eaddr, unsigned short eport,
|
||||||
|
@ -222,8 +228,13 @@ add_redirect_rule2(const char * ifname,
|
||||||
UNUSED(ifname);
|
UNUSED(ifname);
|
||||||
|
|
||||||
r = addnatrule(proto, eport, iaddr, iport, rhost);
|
r = addnatrule(proto, eport, iaddr, iport, rhost);
|
||||||
if(r >= 0)
|
if(r >= 0) {
|
||||||
add_redirect_desc(eport, proto, desc, timestamp);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,6 +1014,29 @@ get_dscp_target(unsigned char dscp)
|
||||||
return target;
|
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()
|
/* iptc_init_verify_and_append()
|
||||||
* return 0 on success, -1 on failure */
|
* return 0 on success, -1 on failure */
|
||||||
static int
|
static int
|
||||||
|
@ -1134,6 +1168,80 @@ addnatrule(int proto, unsigned short eport,
|
||||||
return r;
|
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
|
/* iptables -t nat -A MINIUPNPD-PCP-PEER -s iaddr -d rhost
|
||||||
* -p proto --sport iport --dport rport -j SNAT
|
* -p proto --sport iport --dport rport -j SNAT
|
||||||
* --to-source ext_ip:eport */
|
* --to-source ext_ip:eport */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
|
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
|
||||||
/* MiniUPnP project
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* 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
|
* This software is subject to the conditions detailed
|
||||||
* in the LICENCE file provided within the distribution */
|
* in the LICENCE file provided within the distribution */
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "iptcrdr.c"
|
#include "iptcrdr.c"
|
||||||
#include "../commonrdr.h"
|
/*#include "../commonrdr.h"*/
|
||||||
|
|
||||||
#ifndef PRIu64
|
#ifndef PRIu64
|
||||||
#define PRIu64 "llu"
|
#define PRIu64 "llu"
|
||||||
|
@ -22,7 +22,9 @@ main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
unsigned short eport, iport;
|
unsigned short eport, iport;
|
||||||
const char * iaddr;
|
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)
|
if(argc<4)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -30,11 +32,22 @@ main(int argc, char ** argv)
|
||||||
eport = (unsigned short)atoi(argv[1]);
|
eport = (unsigned short)atoi(argv[1]);
|
||||||
iaddr = argv[2];
|
iaddr = argv[2];
|
||||||
iport = (unsigned short)atoi(argv[3]);
|
iport = (unsigned short)atoi(argv[3]);
|
||||||
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
|
if(argc >= 4) {
|
||||||
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport, NULL) < 0)
|
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;
|
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;
|
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 */
|
/* test */
|
||||||
{
|
{
|
||||||
unsigned short p1, p2;
|
unsigned short p1, p2;
|
||||||
|
@ -63,8 +76,8 @@ main(int argc, char ** argv)
|
||||||
}
|
}
|
||||||
printf("trying to list nat rules :\n");
|
printf("trying to list nat rules :\n");
|
||||||
list_redirect_rule(argv[1]);
|
list_redirect_rule(argv[1]);
|
||||||
printf("deleting\n");
|
//printf("deleting\n");
|
||||||
delete_redirect_and_filter_rules(eport, IPPROTO_TCP);
|
//delete_redirect_and_filter_rules(eport, proto);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue