miniupnpd: filter HTTP and SSDP based on source IP

Check source address of incomining HTTP connections and SSDP
packets in order to filter out WAN SSDP and HTTP trafic.
This commit is contained in:
Thomas Bernard 2013-02-06 15:20:04 +01:00
parent 43d3939602
commit c7419a5de6
5 changed files with 137 additions and 46 deletions

View File

@ -1,6 +1,8 @@
$Id: Changelog.txt,v 1.325 2013/02/06 13:14:50 nanard Exp $
2013/02/06:
Check source address of incomining HTTP connections and SSDP
packets in order to filter out WAN SSDP and HTTP trafic.
Implement get_src_for_route_to() for *BSD
fix 2 potential memory leaks in GetListOfPortMappings()

View File

@ -554,6 +554,13 @@ ProcessSSDPData(int s, const char *bufr, int n,
/* get the string representation of the sender address */
sockaddr_to_string(sender, sender_str, sizeof(sender_str));
lan_addr = get_lan_for_peer(sender);
if(lan_addr == NULL)
{
syslog(LOG_WARNING, "SSDP packet sender %s not from a LAN, ignoring",
sender_str);
return;
}
if(memcmp(bufr, "NOTIFY", 6) == 0)
{
@ -597,14 +604,6 @@ ProcessSSDPData(int s, const char *bufr, int n,
/* find in which sub network the client is */
if(sender->sa_family == AF_INET)
{
for(lan_addr = lan_addrs.lh_first;
lan_addr != NULL;
lan_addr = lan_addr->list.le_next)
{
if( (((const struct sockaddr_in *)sender)->sin_addr.s_addr & lan_addr->mask.s_addr)
== (lan_addr->addr.s_addr & lan_addr->mask.s_addr))
break;
}
if (lan_addr == NULL)
{
syslog(LOG_ERR, "Can't find in which sub network the client is");

View File

@ -1,7 +1,7 @@
/* $Id: miniupnpd.c,v 1.172 2012/12/11 21:07:36 nanard Exp $ */
/* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -1789,6 +1789,16 @@ main(int argc, char * * argv)
sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
syslog(LOG_INFO, "HTTP connection from %s", addr_str);
if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
{
/* The peer is not a LAN ! */
syslog(LOG_WARNING,
"HTTP peer %s is not from a LAN, closing the connection",
addr_str);
close(shttp);
}
else
{
/* Create a new upnphttp object and add it to
* the active upnphttp object list */
tmp = New_upnphttp(shttp);
@ -1828,6 +1838,7 @@ main(int argc, char * * argv)
}
}
}
}
#ifdef ENABLE_NFQUEUE
/* process NFQ packets */
if(nfqh >= 0 && FD_ISSET(nfqh, &readset))

View File

@ -1,13 +1,15 @@
/* $Id: upnputils.c,v 1.5 2012/05/24 16:51:09 nanard Exp $ */
/* $Id: upnputils.c,v 1.6 2013/02/06 10:50:04 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
@ -19,6 +21,10 @@
#endif
#include "upnputils.h"
#include "upnpglobalvars.h"
#ifdef ENABLE_IPV6
#include "getroute.h"
#endif
int
sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size)
@ -83,3 +89,70 @@ set_non_blocking(int fd)
return 1;
}
struct lan_addr_s *
get_lan_for_peer(const struct sockaddr * peer)
{
struct lan_addr_s * lan_addr = NULL;
#ifdef ENABLE_IPV6
if(peer->sa_family == AF_INET6)
{
struct sockaddr_in6 * peer6 = (struct sockaddr_in6 *)peer;
if(IN6_IS_ADDR_V4MAPPED(&peer6->sin6_addr))
{
struct in_addr peer_addr;
memcpy(&peer_addr, &peer6->sin6_addr.s6_addr[12], 4);
for(lan_addr = lan_addrs.lh_first;
lan_addr != NULL;
lan_addr = lan_addr->list.le_next)
{
if( (peer_addr.s_addr & lan_addr->mask.s_addr)
== (lan_addr->addr.s_addr & lan_addr->mask.s_addr))
break;
}
}
else
{
int index = -1;
if(get_src_for_route_to(peer, NULL, NULL, &index) < 0)
return NULL;
syslog(LOG_DEBUG, "%s looking for LAN interface index=%d",
"get_lan_for_peer()", index);
for(lan_addr = lan_addrs.lh_first;
lan_addr != NULL;
lan_addr = lan_addr->list.le_next)
{
syslog(LOG_DEBUG,
"ifname=%s index=%u str=%s addr=%08x mask=%08x",
lan_addr->ifname, lan_addr->index,
lan_addr->str,
ntohl(lan_addr->addr.s_addr),
ntohl(lan_addr->mask.s_addr));
if(index == (int)lan_addr->index)
break;
}
}
}
else if(peer->sa_family == AF_INET)
{
#endif
for(lan_addr = lan_addrs.lh_first;
lan_addr != NULL;
lan_addr = lan_addr->list.le_next)
{
if( (((const struct sockaddr_in *)peer)->sin_addr.s_addr & lan_addr->mask.s_addr)
== (lan_addr->addr.s_addr & lan_addr->mask.s_addr))
break;
}
#ifdef ENABLE_IPV6
}
#endif
if(lan_addr)
syslog(LOG_DEBUG, "%s: found in LAN %s %s",
"get_lan_for_peer()", lan_addr->ifname, lan_addr->str);
else
syslog(LOG_DEBUG, "%s: not found !", "get_lan_for_peer()");
return lan_addr;
}

View File

@ -1,7 +1,7 @@
/* $Id: upnputils.h,v 1.2 2012/02/06 16:21:24 nanard Exp $ */
/* $Id: upnputils.h,v 1.4 2013/02/06 10:50:04 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard
* (c) 2011-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -23,5 +23,11 @@ sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size);
int
set_non_blocking(int fd);
/**
* get the LAN which the peer belongs to
*/
struct lan_addr_s *
get_lan_for_peer(const struct sockaddr * peer);
#endif