diff --git a/pdns/backends/bind/bindbackend2.cc b/pdns/backends/bind/bindbackend2.cc
index 22fee2b..9ec657c 100644
--- a/pdns/backends/bind/bindbackend2.cc
+++ b/pdns/backends/bind/bindbackend2.cc
@@ -248,6 +248,19 @@ bool Bind2Backend::checkACL(const string &acl_type, const string &key, const str
       }
     }
   }
+  else if (acl_type=="allow-query") {
+    shared_ptr<State> state = s_state;
+    for(id_zone_map_t::const_iterator i = state->id_zone_map.begin(); i != state->id_zone_map.end() ; ++i) {
+      if(i->second.d_name==key) {
+        for(vector<string>::const_iterator k=i->second.d_allowquery.begin();k!=i->second.d_allowquery.end();++k) {
+          Netmask nm(*k);
+          if (nm.match(value)) {
+       return true;
+     }
+        }
+      }
+    }
+  }
   return false;
 }
 
@@ -595,6 +608,7 @@ void Bind2Backend::loadConfig(string* status)
    bbd->d_masters=i->masters;
    bbd->d_alsonotify=i->alsonotify;
    bbd->d_allowtransfer=i->allowtransfer;
+   bbd->d_allowquery=i->allowquery;
    
    if(!bbd->d_loaded || !bbd->current()) {
      //     L<<Logger::Info<<d_logprefix<<" parsing '"<<i->name<<"' from file '"<<i->filename<<"'"<<endl;
diff --git a/pdns/backends/bind/bindbackend2.hh b/pdns/backends/bind/bindbackend2.hh
index b9e9032..b90d9d7 100644
--- a/pdns/backends/bind/bindbackend2.hh
+++ b/pdns/backends/bind/bindbackend2.hh
@@ -77,6 +77,7 @@ public:
   vector<string> d_masters;     //!< IP address of the master of this domain
   vector<string> d_alsonotify; //!< list the IP addresses that need notifications for the given domain
   vector<string> d_allowtransfer; //!< Only these netmasks are allowed to transfer this domain
+  vector<string> d_allowquery; //!< Only these netmasks are allowed to lookup on this domain
 
   uint32_t d_lastnotified; //!< Last serial number we notified our slaves of
 
diff --git a/pdns/backends/bind/bindlexer.l b/pdns/backends/bind/bindlexer.l
index 04c22e8..2786c29 100644
--- a/pdns/backends/bind/bindlexer.l
+++ b/pdns/backends/bind/bindlexer.l
@@ -115,6 +115,7 @@ directory               return DIRECTORYTOK;
 masters                 return MASTERTOK;
 also-notify             return ALSONOTIFYOK;
 allow-transfer          return ALLOWTRANSFEROK;
+allow-query             return ALLOWQUERYOK;
 type                    return TYPETOK;
 \"                      yy_push_state(quoted);
 <quoted>[^\"]*          yylval=strdup(yytext); return QUOTEDWORD;
diff --git a/pdns/backends/bind/bindparser.hh b/pdns/backends/bind/bindparser.hh
index 3651491..f43de71 100644
--- a/pdns/backends/bind/bindparser.hh
+++ b/pdns/backends/bind/bindparser.hh
@@ -36,6 +36,7 @@ public:
     masters.clear();
     alsonotify.clear();
     allowtransfer.clear();
+    allowquery.clear();
     d_dev=0;
     d_ino=0;
   }
@@ -44,6 +45,7 @@ public:
   vector<string> masters;
   vector<string> alsonotify;
   vector<string> allowtransfer;
+  vector<string> allowquery;
   string type;
     
   dev_t d_dev;
diff --git a/pdns/backends/bind/bindparser.yy b/pdns/backends/bind/bindparser.yy
index 8fb55a9..981199f 100644
--- a/pdns/backends/bind/bindparser.yy
+++ b/pdns/backends/bind/bindparser.yy
@@ -101,7 +101,7 @@ void BindParser::commit(BindDomainInfo DI)
 %}
 
 %token AWORD QUOTEDWORD OBRACE EBRACE SEMICOLON ZONETOK FILETOK OPTIONSTOK
-%token DIRECTORYTOK ACLTOK LOGGINGTOK CLASSTOK TYPETOK MASTERTOK ALSONOTIFYOK ALLOWTRANSFEROK
+%token DIRECTORYTOK ACLTOK LOGGINGTOK CLASSTOK TYPETOK MASTERTOK ALSONOTIFYOK ALLOWTRANSFEROK ALLOWQUERYOK
 
 %%
 
@@ -200,7 +200,7 @@ zone_commands:
    zone_commands zone_command SEMICOLON
    ;
 
-zone_command: command | zone_file_command | zone_type_command | zone_masters_command | zone_alsonotify_command | zone_allowtransfer_command
+zone_command: command | zone_file_command | zone_type_command | zone_masters_command | zone_alsonotify_command | zone_allowtransfer_command | zone_allowquery_command
    ;
 
 zone_masters_command: MASTERTOK OBRACE masters EBRACE
@@ -265,6 +265,21 @@ transfer: AWORD
    }
    ;
 
+zone_allowquery_command: ALLOWQUERYOK OBRACE allowquery EBRACE
+   ;
+
+allowquery: /* empty */
+   | 
+   allowquery allowed_subnet SEMICOLON 
+   ;
+
+allowed_subnet: AWORD
+   {
+      s_di.allowquery.push_back($1);
+      free($1);
+   }
+   ;
+
 quotedname:
    QUOTEDWORD
    {
diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc
index 0b9bdfa..9c0477f 100644
--- a/pdns/common_startup.cc
+++ b/pdns/common_startup.cc
@@ -116,6 +116,7 @@ void declareArguments()
   arg().set("max-tcp-connections","Maximum number of TCP connections")="10";
   arg().setSwitch("no-shuffle","Set this to prevent random shuffling of answers - for regression testing")="off";
   arg().setSwitch("per-zone-axfr-acls","When set, backends that implement it perform per-zone AXFL ACL checks")="off";
+  arg().setSwitch("per-zone-query-acls","When set, backends that implement it perform per-zone Query ACL checks")="off";
 
   arg().setSwitch( "use-logfile", "Use a log file" )= "no";
   arg().set( "logfile", "Logfile to use" )= "pdns.log";
diff --git a/pdns/nameserver.hh b/pdns/nameserver.hh
index 88602c2..2560c0e 100644
--- a/pdns/nameserver.hh
+++ b/pdns/nameserver.hh
@@ -31,6 +31,8 @@
 #endif // WIN32
 
 #include <vector>
+#include "arguments.hh"
+#include "packethandler.hh"
 #include "statbag.hh"
 using namespace std;
 
@@ -152,7 +154,21 @@ inline DNSPacket *UDPNameserver::receive(DNSPacket *prefilled)
       delete packet;
     return 0; // unable to parse
   }
-  
+
+  if(arg().mustDo("per-zone-query-acls")) {
+    SOAData sd;
+    PacketHandler P;
+    sd.db=(DNSBackend *)-1;
+    if(P.getBackend()->getSOA(packet->qdomain,sd)) {
+      DNSBackend *B=sd.db;
+      if (!B->checkACL(string("allow-query"), packet->qdomain, packet->getRemote())) {
+        if(!prefilled)
+          delete packet;
+        return 0; // unable to parse
+      }
+    }
+  }
+
   return packet;
 }
 
diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc
index 10d8f37..ccbd335 100644
--- a/pdns/tcpreceiver.cc
+++ b/pdns/tcpreceiver.cc
@@ -277,6 +277,17 @@ void *TCPNameserver::doConnection(void *data)
    continue;
       }
 
+      if(arg().mustDo("per-zone-query-acls")) {
+        SOAData sd;
+        sd.db=(DNSBackend *)-1;
+        if(s_P->getBackend()->getSOA(packet->qdomain,sd)) {
+          DNSBackend *B=sd.db;
+          if (!B->checkACL(string("allow-query"), packet->qdomain, packet->getRemote())) {
+       break;
+          }
+        }
+      }
+
       shared_ptr<DNSPacket> reply; 
       shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new DNSPacket);
 
@@ -353,7 +364,7 @@ bool TCPNameserver::canDoAXFR(shared_ptr<DNSPacket> q)
       if (B->checkACL(string("allow-axfr"), q->qdomain, q->getRemote())) {
    return true;
       }
-    }  
+    }
   }
 
   extern CommunicatorClass Communicator;
