uhttpd: add option to reject requests from RFC1918 IPs to public server IPs (DNS rebinding countermeasure)
SVN-Revision: 22589
This commit is contained in:
parent
a5371dfe39
commit
3d99f03082
7 changed files with 38 additions and 2 deletions
|
@ -8,7 +8,7 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=uhttpd
|
PKG_NAME:=uhttpd
|
||||||
PKG_RELEASE:=12
|
PKG_RELEASE:=13
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
PKG_BUILD_DEPENDS := libcyassl liblua
|
PKG_BUILD_DEPENDS := libcyassl liblua
|
||||||
|
|
|
@ -12,6 +12,11 @@ config uhttpd main
|
||||||
# Server document root
|
# Server document root
|
||||||
option home /www
|
option home /www
|
||||||
|
|
||||||
|
# Reject requests from RFC1918 IP addresses
|
||||||
|
# directed to the servers public IP(s).
|
||||||
|
# This is a DNS rebinding countermeasure.
|
||||||
|
option rfc1918_filter 1
|
||||||
|
|
||||||
# Certificate and private key for HTTPS.
|
# Certificate and private key for HTTPS.
|
||||||
# If no listen_https addresses are given,
|
# If no listen_https addresses are given,
|
||||||
# the key options are ignored.
|
# the key options are ignored.
|
||||||
|
|
|
@ -75,6 +75,7 @@ start_instance()
|
||||||
|
|
||||||
append_bool "$cfg" no_symlinks "-S" 0
|
append_bool "$cfg" no_symlinks "-S" 0
|
||||||
append_bool "$cfg" no_dirlists "-D" 0
|
append_bool "$cfg" no_dirlists "-D" 0
|
||||||
|
append_bool "$cfg" rfc1918_filter "-R" 0
|
||||||
|
|
||||||
config_get http "$cfg" listen_http
|
config_get http "$cfg" listen_http
|
||||||
for listen in $http; do
|
for listen in $http; do
|
||||||
|
|
|
@ -59,6 +59,21 @@ int sa_port(void *sa)
|
||||||
return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
|
return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sa_rfc1918(void *sa)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *v4 = (struct sockaddr_in *)sa;
|
||||||
|
unsigned long a = htonl(v4->sin_addr.s_addr);
|
||||||
|
|
||||||
|
if( v4->sin_family == AF_INET )
|
||||||
|
{
|
||||||
|
return ((a >= 0x0A000000) && (a <= 0x0AFFFFFF)) ||
|
||||||
|
((a >= 0xAC100000) && (a <= 0xAC1FFFFF)) ||
|
||||||
|
((a >= 0xC0A80000) && (a <= 0xC0A8FFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Simple strstr() like function that takes len arguments for both haystack and needle. */
|
/* Simple strstr() like function that takes len arguments for both haystack and needle. */
|
||||||
char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
|
char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,6 +49,7 @@ struct path_info {
|
||||||
const char * sa_straddr(void *sa);
|
const char * sa_straddr(void *sa);
|
||||||
const char * sa_strport(void *sa);
|
const char * sa_strport(void *sa);
|
||||||
int sa_port(void *sa);
|
int sa_port(void *sa);
|
||||||
|
int sa_rfc1918(void *sa);
|
||||||
|
|
||||||
char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
|
char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
|
||||||
|
|
||||||
|
|
|
@ -524,7 +524,7 @@ int main (int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while( (opt = getopt(argc, argv,
|
while( (opt = getopt(argc, argv,
|
||||||
"fSDC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0
|
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0
|
||||||
) {
|
) {
|
||||||
switch(opt)
|
switch(opt)
|
||||||
{
|
{
|
||||||
|
@ -648,6 +648,10 @@ int main (int argc, char **argv)
|
||||||
conf.no_dirlists = 1;
|
conf.no_dirlists = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
conf.rfc1918_filter = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_CGI
|
#ifdef HAVE_CGI
|
||||||
/* cgi prefix */
|
/* cgi prefix */
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -728,6 +732,7 @@ int main (int argc, char **argv)
|
||||||
" -I string Use given filename as index page for directories\n"
|
" -I string Use given filename as index page for directories\n"
|
||||||
" -S Do not follow symbolic links outside of the docroot\n"
|
" -S Do not follow symbolic links outside of the docroot\n"
|
||||||
" -D Do not allow directory listings, send 403 instead\n"
|
" -D Do not allow directory listings, send 403 instead\n"
|
||||||
|
" -R Enable RFC1918 filter\n"
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
||||||
" -L file Lua handler script, omit to disable Lua\n"
|
" -L file Lua handler script, omit to disable Lua\n"
|
||||||
|
@ -932,6 +937,14 @@ int main (int argc, char **argv)
|
||||||
/* parse message header */
|
/* parse message header */
|
||||||
if( (req = uh_http_header_recv(cl)) != NULL )
|
if( (req = uh_http_header_recv(cl)) != NULL )
|
||||||
{
|
{
|
||||||
|
/* RFC1918 filtering required? */
|
||||||
|
if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) &&
|
||||||
|
!sa_rfc1918(&cl->servaddr) )
|
||||||
|
{
|
||||||
|
uh_http_sendhf(cl, 403, "Forbidden",
|
||||||
|
"Rejected request from RFC1918 IP to public server address");
|
||||||
|
}
|
||||||
|
else
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
/* Lua request? */
|
/* Lua request? */
|
||||||
if( L && uh_path_match(conf.lua_prefix, req->url) )
|
if( L && uh_path_match(conf.lua_prefix, req->url) )
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct config {
|
||||||
int no_symlinks;
|
int no_symlinks;
|
||||||
int no_dirlists;
|
int no_dirlists;
|
||||||
int network_timeout;
|
int network_timeout;
|
||||||
|
int rfc1918_filter;
|
||||||
#ifdef HAVE_CGI
|
#ifdef HAVE_CGI
|
||||||
char *cgi_prefix;
|
char *cgi_prefix;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue