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:
parent
43d3939602
commit
c7419a5de6
|
@ -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()
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,42 +1789,53 @@ 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);
|
||||
/* Create a new upnphttp object and add it to
|
||||
* the active upnphttp object list */
|
||||
tmp = New_upnphttp(shttp);
|
||||
if(tmp)
|
||||
if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
if(clientname.ss_family == AF_INET)
|
||||
{
|
||||
tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
|
||||
}
|
||||
else if(clientname.ss_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
|
||||
if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
|
||||
{
|
||||
memcpy(&tmp->clientaddr,
|
||||
&addr->sin6_addr.s6_addr[12],
|
||||
4);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->ipv6 = 1;
|
||||
memcpy(&tmp->clientaddr_v6,
|
||||
&addr->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
}
|
||||
#else
|
||||
tmp->clientaddr = clientname.sin_addr;
|
||||
#endif
|
||||
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
|
||||
/* 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
|
||||
{
|
||||
syslog(LOG_ERR, "New_upnphttp() failed");
|
||||
close(shttp);
|
||||
/* Create a new upnphttp object and add it to
|
||||
* the active upnphttp object list */
|
||||
tmp = New_upnphttp(shttp);
|
||||
if(tmp)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
if(clientname.ss_family == AF_INET)
|
||||
{
|
||||
tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
|
||||
}
|
||||
else if(clientname.ss_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
|
||||
if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
|
||||
{
|
||||
memcpy(&tmp->clientaddr,
|
||||
&addr->sin6_addr.s6_addr[12],
|
||||
4);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->ipv6 = 1;
|
||||
memcpy(&tmp->clientaddr_v6,
|
||||
&addr->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
}
|
||||
#else
|
||||
tmp->clientaddr = clientname.sin_addr;
|
||||
#endif
|
||||
LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, "New_upnphttp() failed");
|
||||
close(shttp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue