]> granicus.if.org Git - pdns/commitdiff
implement 'back mapping' for IPv4 addresses mapped to IPv6, so things 'just work...
authorBert Hubert <bert.hubert@netherlabs.nl>
Mon, 8 May 2006 07:15:35 +0000 (07:15 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Mon, 8 May 2006 07:15:35 +0000 (07:15 +0000)
IPv4 addresses to IPv6 for allow-from. Noted by Marcus Rueckert.
Added ::1/128 to default allow-from, as well as fe80::/16.

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@826 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/iputils.hh
pdns/pdns_recursor.cc

index d3bd92c1c4d8dbcd3b1e438523bbaea7e212344f..f7a96c06e05ccf6556d35d783efb5c2db88d7461 100644 (file)
@@ -105,6 +105,38 @@ union ComboAddress {
     }
   }
 
+  bool isMappedIPv4()  
+  {
+    if(sin4.sin_family!=AF_INET6)
+      return false;
+    
+    int n=0;
+    const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
+    for(n=0; n < 10; ++n)
+      if(ptr[n])
+       return false;
+    
+    for(; n < 12; ++n)
+      if(ptr[n]!=0xff)
+       return false;
+    
+    return true;
+  }
+  
+  ComboAddress mapToIPv4()  
+  {
+    if(!isMappedIPv4())
+      throw AhuException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
+    ComboAddress ret;
+    ret.sin4.sin_family=AF_INET;
+    ret.sin4.sin_port=0;
+    
+    const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
+    ptr+=12;
+    memcpy(&ret.sin4.sin_addr.s_addr, ptr, 4);
+    return ret;
+  }
+
   string toString() const
   {
     char tmp[128];
@@ -161,6 +193,11 @@ public:
       d_bits=128;
   }
 
+  bool match(const ComboAddress& ip) const
+  {
+    return match(&ip);
+  }
+
   //! If this IP address in socket address matches
   bool match(const ComboAddress *ip) const
   {
@@ -217,7 +254,7 @@ public:
   bool match(ComboAddress *ip)
   {
     for(container_t::const_iterator i=d_masks.begin();i!=d_masks.end();++i)
-      if(i->match(ip))
+      if(i->match(ip) || (ip->isMappedIPv4() && i->match(ip->mapToIPv4()) ))
        return true;
 
     return false;
index 0b480a3aef0c30d71551ab1cf2bab9cc8d37977c..2f6fd72db41ccb4d7ee2546309f652e68fc78ff6 100644 (file)
@@ -683,6 +683,9 @@ void handleNewTCPQuestion(int fd, boost::any& )
   if(newsock>0) {
     g_stats.addRemote(addr);
     if(g_allowFrom && !g_allowFrom->match(&addr)) {
+      if(!g_quiet) 
+       L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
+
       g_stats.unauthorizedTCP++;
       Utility::closesocket(newsock);
       return;
@@ -708,7 +711,7 @@ void handleNewTCPQuestion(int fd, boost::any& )
     g_fdm->setReadTTD(tc.fd, now, g_tcpTimeout);
   }
 }
-
 void handleNewUDPQuestion(int fd, boost::any& var)
 {
   int len;
@@ -719,6 +722,10 @@ void handleNewUDPQuestion(int fd, boost::any& var)
   if((len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) {
     g_stats.addRemote(fromaddr);
     if(g_allowFrom && !g_allowFrom->match(&fromaddr)) {
+      cout<<"mapped: "<<fromaddr.isMappedIPv4()<<endl;
+      if(!g_quiet) 
+       L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
+
       g_stats.unauthorizedUDP++;
       return;
     }
@@ -1586,7 +1593,7 @@ int main(int argc, char **argv)
     ::arg().set("server-id", "Returned when queried for 'server.id' TXT, defaults to hostname")="";
     ::arg().set("remotes-ringbuffer-entries", "maximum number of packets to store statistics for")="0";
     ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Recursor "VERSION" $Id$";
-    ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12";
+    ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/16";
     ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
     ::arg().set("fork", "If set, fork the daemon for possible double performance")="no";
     ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";