[Dnsmasq-discuss] localise-queries does not work with ipv6

2017-06-22 Thread Jason A. Donenfeld
Hello Simon,

In dnsmasq.conf:

interface-name=martino,lan  # 10.10.10.1, 2a07:f32:8fe8:8a61::1
interface-name=martino,guest # 10.11.0.1, 2a07:f32:8fe8:8a63::1
interface-name=martino,remote # 10.10.11.1, 2a07:f32:8fe8:8a62::1
localise-queries

zx2c4@thinkpad ~ $ host martino 10.10.10.1
Using domain server:
Name: 10.10.10.1
Address: 10.10.10.1#53
Aliases:

martino has address 10.10.10.1
martino has IPv6 address 2a07:f32:8fe8:8a61::1
martino has IPv6 address 2a07:f32:8fe8:8a63::1
martino has IPv6 address 2a07:f32:8fe8:8a62::1

You'll notice it correctly filters the v4, but totally fails to do any
v6 filtering. Even worse:

zx2c4@thinkpad ~ $ host martino 2a07:f32:8fe8:8a61::1
Using domain server:
Name: 2a07:f32:8fe8:8a61::1
Address: 2a07:f32:8fe8:8a61::1#53
Aliases:

martino has address 10.10.10.1
martino has address 10.10.11.1
martino has address 10.11.0.1
martino has IPv6 address 2a07:f32:8fe8:8a61::1
martino has IPv6 address 2a07:f32:8fe8:8a63::1
martino has IPv6 address 2a07:f32:8fe8:8a62::1

Here it doesn't do any filtering at all.

It seems like localise-queries is broken with v6?

Jason

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] interface-specific DNS entries

2017-06-22 Thread Jason A. Donenfeld
--localise-queries

Sorry for the noise.

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] interface-specific DNS entries

2017-06-22 Thread Jason A. Donenfeld
Hey folks,

I use the interface-name directive like this:

interface-name=martino,lan
interface-name=martino,guest
interface-name=martino,remote

This has the consequence of seeing all the IPs at once for this domain:

zx2c4@thinkpad ~ $ host martino
martino has address 10.10.10.1
martino has address 10.11.0.1
martino has address 10.10.11.1

Instead of this, I'd like for dnsmasq to return lan's IP when the DNS
request comes via lan, guest's IP when the DNS request comes via
guest, and remote's IP when the DNS request comes via remote.

Is it possible to bind certain DNS responses to a particular
interface? More generally, it'd be nice to be able to use the tag:
directive with DNS entries, such as:

interface-name=tag:lan,martino,lan
interface-name=tag:guest,martino,guest
interface-name=tag:remote,martino,remote

Thanks,
Jason

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] Using nftables internal "ipset" rule

2017-06-16 Thread Jason A. Donenfeld
Hey Simon,

Fast forward 5 years from when I wrote the original ipset patch for
dnsmasq, and I too have a need for nftables support with it. Did you
ever figure out how to add nft sets to dnsmasq? If not, maybe I'll
take a stab at it in the next few months.

Jason

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [PATCH v2] Optimize ipset/server/local/address/rebind-domain-ok performance

2015-02-27 Thread Jason A. Donenfeld
I wrote something similar here a while back:
http://git.zx2c4.com/domain-lookup-tree/about/


Your algorithm looks potentially more efficient.

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] localise-queries with interface-name

2015-02-27 Thread Jason A. Donenfeld
Hi Simon,

Right now I have in my /etc/hosts file the following:

10.59.0.1vitrycore.office.grafitroniks.fr vitrycore
10.59.248.1  vitrycore.office.grafitroniks.fr vitrycore
10.59.32.1   vitrycore.office.grafitroniks.fr vitrycore
10.59.252.1  vitrycore.office.grafitroniks.fr vitrycore
192.168.1.1  vitrycore.office.grafitroniks.fr vitrycore

And then in my dnsmasq config I have

localise-queries

The result is that depending on the interface, the right IP will be returned.

I'd rather not hard code this in /etc/hosts, however. Instead it'd be
nice to use the interface-name options, so that I could write:

localise-queries
interface-name=vitrycore.office.grafitroniks.fr,eth6.10
interface-name=vitrycore.office.grafitroniks.fr,eth6.80
interface-name=vitrycore.office.grafitroniks.fr,eth6.200
interface-name=vitrycore.office.grafitroniks.fr,eth7
interface-name=vitrycore.office.grafitroniks.fr,vtun0

And then localise-queries would serve the correct one, depending on
the interface.

More generally, it'd be nice if the localise-queries option could work
for *all* specified records, not just those in /etc/hosts.

What do you think?

Jason

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] Enable HAVE_IPSET by default

2013-03-20 Thread Jason A. Donenfeld
Hi Simon,

It's just occurred to me that no router developer is going to know to
turn HAVE_IPSET on, and hence, it won't be available immediately on any
devices, which is a bummer. Further, unless the --ipset= options are
used, HAVE_IPSET doesn't contribute at _all_ to the runtime of the app. And
even further, if HAVE_LINUX_NETWORK isn't enabled, HAVE_IPSET is
automatically disabled.

Makes sense, then, I think, to uncomment HAVE_IPSET by default.

How about it?

Jason
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-22 Thread Jason A. Donenfeld
On Wed, Feb 20, 2013 at 3:17 PM, Kaspar Schleiser wrote:
>
> Could you elaborate on how your tree works?


Went ahead and annotated the source:
http://git.zx2c4.com/domain-lookup-tree/tree/domain-lookup.c
Should be way easier to understand what's up.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-21 Thread Jason A. Donenfeld
On Wed, Feb 20, 2013 at 9:53 PM, Jason A. Donenfeld  wrote:

> Okie dokie, benchmark time! 2012 Intel Core i7, gcc 4.7.2.
>

Looks like gcc was optimizing out the legacy test. Fixed that, and added
some data verification.

zx2c4@thinkpad ~/Projects/domain-lookup-tree $ make
cc -march=native -pipe -fomit-frame-pointer -flto -O3test.c
domain-lookup.c domain-lookup.h   -o test
cc -march=native -pipe -fomit-frame-pointer -flto -O3benchmark.c
domain-lookup.c domain-lookup.h   -o benchmark

zx2c4@thinkpad ~/Projects/domain-lookup-tree $ ./benchmark
[+] Populating in memory word list.
[+] Creating random lists of domains to query.
[+] Populating domain lookup tree.
[+] Performing lookup benchmarks:
[*] New method took 0.37 seconds.
[*] Old method took 188.77 seconds.
[+] Verifying that new and old methods produced identical results:
[*] New and old methods produced the same results.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-20 Thread Jason A. Donenfeld
On Wed, Feb 20, 2013 at 5:46 PM, Simon Kelley wrote:
>
> I'm
> currently snowed under (at least partially with your earlier good work)
> so I may not get to this for a while.


No problem. Upstreaming the ipset code is a much bigger priority in my
book. This optimization code is mainly just something to play around with.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-20 Thread Jason A. Donenfeld
On Wed, Feb 20, 2013 at 3:17 PM, Kaspar Schleiser wrote:

> Did you do any benchmarks?


Okie dokie, benchmark time! 2012 Intel Core i7, gcc 4.7.2.

With gcc's -O3:

zx2c4@thinkpad ~/Projects/domain-lookup-tree $ ./benchmark
New method took 0.43 seconds.
Old method took 2.75 seconds.


Without -O3:

zx2c4@thinkpad ~/Projects/domain-lookup-tree $ ./benchmark
New method took 0.41 seconds.
Old method took 325.94 seconds.


Benchmarking code is in previously linked git repository.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-20 Thread Jason A. Donenfeld
On Wed, Feb 20, 2013 at 3:17 PM, Kaspar Schleiser wrote:
>
> Could you elaborate on how your tree works? Did you do any benchmarks?


Each node represents a domain component.

* -> [com -> [zx2c4 -> [data, blog ], kexec ], org -> [slashdot ] ]

It splits the domain string by the period, and then walks the components
backward.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [Request for Comments] Optimized Nearest-Domain Lookup

2013-02-20 Thread Jason A. Donenfeld
Hi Simon & Folks,

Currently when dnsmasq processes server=/.../, address=/.../, local=/.../,
ipset=/.../, and similar, it find the nearest match for a domain name by
iterating through all the keys, and keeping track of which one had the
largest match length. This gets the job done and is fairly, simple. But it
also could be optimized quite a bit.

This might be a bit verbose for dnsmasq's tastes, and maybe the notion
smells a bit too much of "My First Computer Science Data Structure" kind of
thing, but perhaps this might be a welcome optimization. I present you with
domain-lookup-tree, a simple set of C functions that store domain names in
a tree structure:

http://git.zx2c4.com/domain-lookup-tree/about/

It should be relatively straightforward. I wrote it specifically with
dnsmasq in mind, so if you're interested, I'd be thrilled to see it replace
the current nieve matching technique.

Thoughts? Comments? Ideas?

Jason
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH v2 1/3] ipset: Integrate ipset.c into build system.

2013-02-17 Thread Jason A. Donenfeld
From: "Jason A. Donenfeld" 

---
 Makefile  |   2 +-
 src/config.h  |  14 +++-
 src/dnsmasq.h |   5 ++
 src/ipset.c   | 220 ++
 4 files changed, 239 insertions(+), 2 deletions(-)
 create mode 100644 src/ipset.c

diff --git a/Makefile b/Makefile
index c9cdb90..7240fbf 100644
--- a/Makefile
+++ b/Makefile
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
 objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
-   dhcp-common.o outpacket.o radv.o slaac.o auth.o
+   dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
 
 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h
diff --git a/src/config.h b/src/config.h
index cff278d..9c8e785 100644
--- a/src/config.h
+++ b/src/config.h
@@ -97,6 +97,10 @@ HAVE_CONNTRACK
a build-dependency on libnetfilter_conntrack, but the resulting binary will
still run happily on a kernel without conntrack support.
 
+HAVE_IPSET
+define this to include the ability to selectively add resolved ip addresses
+to given ipsets.
+
 HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
@@ -136,7 +140,7 @@ RESOLVFILE
 /* #define HAVE_DBUS */
 /* #define HAVE_IDN */
 /* #define HAVE_CONNTRACK */
-
+/* #define HAVE_IPSET */
 
 
 /* Default locations for important system files. */
@@ -323,6 +327,10 @@ HAVE_SOCKADDR_SA_LEN
 #undef HAVE_AUTH
 #endif
 
+#ifndef HAVE_LINUX_NETWORK
+#undef HAVE_IPSET
+#endif
+
 /* Define a string indicating which options are in use.
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
 
@@ -381,6 +389,10 @@ static char *compile_opts =
 "no-"
 #endif
 "conntrack "
+#ifndef HAVE_IPSET
+"no-"
+#endif
+"ipset "
 #ifndef HAVE_AUTH
 "no-"
 #endif
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 21a309c..832e04a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1117,6 +1117,11 @@ void emit_dbus_signal(int action, struct dhcp_lease 
*lease, char *hostname);
 #  endif
 #endif
 
+/* ipset.c */
+#ifdef HAVE_IPSET
+int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, 
int remove);
+#endif
+
 /* helper.c */
 #if defined(HAVE_SCRIPT)
 int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
diff --git a/src/ipset.c b/src/ipset.c
new file mode 100644
index 000..fcf6e25
--- /dev/null
+++ b/src/ipset.c
@@ -0,0 +1,220 @@
+/* ipset.c is Copyright (c) 2013 Jason A. Donenfeld . All 
Rights Reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#ifndef NFNL_SUBSYS_IPSET
+#define NFNL_SUBSYS_IPSET 6
+#define IPSET_ATTR_DATA 7
+#define IPSET_ATTR_IP 1
+#define IPSET_ATTR_IPADDR_IPV4 1
+#define IPSET_ATTR_IPADDR_IPV6 2
+#define IPSET_ATTR_PROTOCOL 1
+#define IPSET_ATTR_SETNAME 2
+#define IPSET_CMD_ADD 9
+#define IPSET_CMD_DEL 10
+#define IPSET_MAXNAMELEN 32
+#define IPSET_PROTOCOL 6
+#else
+#include 
+#endif
+#ifdef HAVE_IPSET
+
+#define NL_ALIGN(len) (((len)+3) & ~(3))
+static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK };
+
+static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, 
const void *data)
+{
+   struct nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
+   uint16_t payload_len = NL_ALIGN(sizeof(struct nlattr)) + len;
+   attr->nla_type = type;
+   attr->nla_len = payload_len;
+   memcpy((void *)attr + NL_ALIGN(sizeof(struct nlattr)), data, len);
+   nlh->nlmsg_len += NL_ALIGN(payload_len);
+}
+
+static int netlink_netfilter_sock()
+{
+   static int fd = -2;
+   if (fd == -2) {
+   fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+   if (fd < 0)
+   return -1;
+   if (bind(fd, (struct sockaddr *)&snl, sizeof(snl)) < 0) {
+   fd = -1;
+   return -1;
+   }
+   }
+   return fd;
+}
+
+static int new_add_to_ipset(const char *

[Dnsmasq-discuss] [PATCH v2 0/3] ipset: Add Netfilter IPSet Support to DNSMasq

2013-02-17 Thread Jason A. Donenfeld
From: "Jason A. Donenfeld" 

This version 2 of the ipset patchset makes a few important changes:

- No HAVE_OLD_IPSET anymore. HAVE_IPSET will enable both, and the
  correct code will then be called depending on the running kernel.

- libmnl is no longer used. All this code was replaced with
  something even more lightweight that should build on old systems.

- The netfilter socket is reused between ipset insertions. Note
  that other netlink sockets used in dnsmasq cannot be reused
  because they're part of a different netlink class, but we're
  smart about reusing the one we do allocate.

- HAVE_IPV6 is now respected, so new code paths won't break on non-
  ipv6 systems.

- compile_opts and various other small fixes

Jason A. Donenfeld (3):
  ipset: Integrate ipset.c into build system.
  ipset: Parse new --ipset option and match domains in forward.c
  ipset: Update man page and example config to reflect new option.

 Makefile |   2 +-
 dnsmasq.conf.example |   4 +
 man/dnsmasq.8|   6 ++
 src/config.h |  14 +++-
 src/dnsmasq.h|  15 +++-
 src/forward.c|  20 -
 src/ipset.c  | 220 +++
 src/option.c |  64 +++
 src/rfc1035.c|  24 +-
 9 files changed, 364 insertions(+), 5 deletions(-)
 create mode 100644 src/ipset.c

-- 
1.8.1.2


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH v2 2/3] ipset: Parse new --ipset option and match domains in forward.c

2013-02-17 Thread Jason A. Donenfeld
From: "Jason A. Donenfeld" 

The matching logic is the same as for --address. extract_address is
responsible for calling out to add_to_ipset.
---
 src/dnsmasq.h | 10 +-
 src/forward.c | 20 ++-
 src/option.c  | 64 +++
 src/rfc1035.c | 24 +-
 4 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 832e04a..9732487 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -430,6 +430,12 @@ struct server {
   struct server *next; 
 };
 
+struct ipsets {
+  char **sets;
+  char *domain;
+  struct ipsets *next;
+};
+
 struct irec {
   union mysockaddr addr;
   struct in_addr netmask; /* only valid for IPv4 */
@@ -779,6 +785,7 @@ extern struct daemon {
   struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
   struct bogus_addr *bogus_addr;
   struct server *servers;
+  struct ipsets *ipsets;
   int log_fac; /* log facility */
   char *log_file; /* optional log file */
   int max_logs;  /* queue limit */
@@ -903,7 +910,8 @@ size_t setup_reply(struct dns_header *header, size_t  qlen,
   struct all_addr *addrp, unsigned int flags,
   unsigned long local_ttl);
 int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
- time_t now, int is_sign, int checkrebind, int 
checking_disabled);
+ time_t now, char **ipsets, int is_sign, int checkrebind,
+ int checking_disabled);
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
   struct in_addr local_addr, struct in_addr local_netmask, 
time_t now);
 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char 
*name, 
diff --git a/src/forward.c b/src/forward.c
index fb0b4c4..f5e95a1 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -439,9 +439,27 @@ static size_t process_reply(struct dns_header *header, 
time_t now,
struct server *server, size_t n, int check_rebind, 
int checking_disabled)
 {
   unsigned char *pheader, *sizep;
+  char **sets = 0;
   int munged = 0, is_sign;
   size_t plen; 
 
+#ifdef HAVE_IPSET
+  /* Similar algorithm to search_servers. */
+  struct ipsets *ipset_pos;
+  unsigned int namelen = strlen(daemon->namebuff);
+  unsigned int matchlen = 0;
+  for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next) {
+ unsigned int domainlen = strlen(ipset_pos->domain);
+ char *matchstart = daemon->namebuff + namelen - domainlen;
+ if (namelen >= domainlen && hostname_isequal(matchstart, 
ipset_pos->domain) &&
+(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == 
'.' ) &&
+domainlen >= matchlen) {
+   matchlen = domainlen;
+   sets = ipset_pos->sets;
+ }
+  }
+#endif
+
   /* If upstream is advertising a larger UDP packet size
  than we allow, trim it so that we don't get overlarge
  requests for the client. We can't do this for signed packets. */
@@ -494,7 +512,7 @@ static size_t process_reply(struct dns_header *header, 
time_t now,
  SET_RCODE(header, NOERROR);
}
   
-  if (extract_addresses(header, n, daemon->namebuff, now, is_sign, 
check_rebind, checking_disabled))
+  if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, 
check_rebind, checking_disabled))
{
  my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), 
daemon->namebuff);
  munged = 1;
diff --git a/src/option.c b/src/option.c
index 3fc3e03..899f4a1 100644
--- a/src/option.c
+++ b/src/option.c
@@ -127,6 +127,7 @@ struct myoption {
 #define LOPT_AUTHSOA   316
 #define LOPT_AUTHSFS   317
 #define LOPT_AUTHPEER  318
+#define LOPT_IPSET 319
 
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
@@ -259,6 +260,7 @@ static const struct myoption opts[] =
 { "auth-soa", 1, 0, LOPT_AUTHSOA },
 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
 { "auth-peer", 1, 0, LOPT_AUTHPEER }, 
+{ "ipset", 1, 0, LOPT_IPSET },
 { NULL, 0, 0, 0 }
   };
 
@@ -397,6 +399,7 @@ static struct {
   { LOPT_AUTHSOA, ARG_ONE, "[,...]", gettext_noop("Set authoritive 
zone information"), NULL },
   { LOPT_AUTHSFS, ARG_DUP, "[,...]", gettext_noop("Secondary 
authoritative nameservers for forward domains"), NULL },
   { LOPT_AUTHPEER, ARG_DUP, "[,...]", gettext_noop("Peers 
which are allowed to do zone transfer"), NULL },
+  { LOPT_IPSET, ARG_DUP, "//[,...]", 
gettext_noop("Specify ipsets to which matching domains should be added"), NULL 
},
   { 0, 0, NULL, NULL, NULL }
 }; 
 
@@ -2021,6 +2024,67 @@ static int one_opt(int option, char *arg, 

[Dnsmasq-discuss] [PATCH v2 3/3] ipset: Update man page and example config to reflect new option.

2013-02-17 Thread Jason A. Donenfeld
From: "Jason A. Donenfeld" 

---
 dnsmasq.conf.example | 4 
 man/dnsmasq.8| 6 ++
 2 files changed, 10 insertions(+)

diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example
index 5215c2a..9a0dbd7 100644
--- a/dnsmasq.conf.example
+++ b/dnsmasq.conf.example
@@ -69,6 +69,10 @@
 # --address (and --server) work with IPv6 addresses too.
 #address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
 
+# Add the IPs of all queries to yahoo.com, google.com, and their
+# subdomains to the vpn and search ipsets:
+#ipset=/yahoo.com/google.com/vpn,search
+
 # You can control how dnsmasq talks to a server: this forces
 # queries to 10.1.2.3 to be routed via eth1
 # server=10.1.2.3@eth1
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index b8dcfc7..941e84d 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -412,6 +412,12 @@ additional facility that /#/ matches any domain. Thus
 answered from /etc/hosts or DHCP and not sent to an upstream
 nameserver by a more specific --server directive.
 .TP
+.B --ipset=//[domain/][,]
+Places the resolved IP addresses of queries for the specified domains
+in the specified netfilter ip sets. Domains and subdomains are matched
+in the same way as --address. These ip sets must already exist. See
+ipset(8) for more details.
+.TP
 .B \-m, --mx-host=[[,],]
 Return an MX record named  pointing to the given hostname (if
 given), or
-- 
1.8.1.2


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [PATCH] Netfilter IPSet Support

2013-02-17 Thread Jason A. Donenfeld
Ahhh great -- I've figured out a nice clean way to remove libmnl and
support both versions of ipset in the same binary. Standby, patches coming
soon!
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [PATCH] Netfilter IPSet Support

2013-02-17 Thread Jason A. Donenfeld
On Sun, Feb 17, 2013 at 6:28 PM, Simon Kelley wrote:
>
> Fantastic! I'm beating my way though my my inbox and just caught up with
> you. I was intending to put this off to the first thing in 2.67, rather
> than the last thing in 2.66, but having got this far, I'm not so sure.
>

Wonderful!


>
> You even wrote the man-page text!
>
> Queries which arise mainly from a fresh pair of eyes:
>
> 1)  Do we need to support HAVE_OLD_IPSET? I can see more reason for 2.4
> kernels that 2.6, but I think most routers are using modern kernels now?
>

We really do need to support old ipset. Lots of broadcom-based routers run
2.6.22, because that's the kernel version broadcom has released their
drivers for. They're extremely widespread, so supporting it is really a
must.

If we do need to support both, I'd like to do both in one binary, just to
> reduce the potential build confusion.


This shouldn't be _too big_ of a problem. I'm rewriting things now to check
utsname on the first invocation of the function, and then route
accordingly. The only potential problem is that since we can't rely on
the existence of the ipset-netlink headers on older systems, I'll have to
import some of those constant values.

Personally I think it's much much much cleaner to have them separate
compile time options, but I understand the build confusion issue too.


> Am I right that the setsockopt method only supports IPv4? So we can't
> support just that.


Older ipsets only support IPv4. They're still extremely useful, but it's a
limitation.



> 2) Can we get by without adding a dependency on libmnl? Do we want to?
>even if we don't, we can replace the code which starts
>

The ipset userland tool uses libmnl, so it's already on the user's system
if they're using ipset. However, this isn't the case if they're using old
ipset, so it might be best to move away from libmnl. I'm investigating that
right now.


>
> mnl = mnl_socket_open(NETLINK_**NETFILTER);
>
> and ends
>
> mnl_socket_close(mnl);
>
> with something which uses the already-existing netlink socket created in
> src/netlink.c, and avoid the overhead of making a new netlink socket on
> each iteration?  Worry about process_reply() being called from the
> TCP-request code-path, from a forked process. I think the netlink socket
> inherited by the forked process will still be OK.
>

If we do stick with libmnl, implementing this will be no problem.


>
> 3)
> (af == AF_INET ? sizeof(ipaddr->addr.addr4) : sizeof(ipaddr->addr.addr4)),
>
> second "addr4" should be "addr6"?
>

Good catch.


>
> 4) The code should compile if HAVE_IPV6 is not set even if the headers
> don't define AF_INET6
>

Roger that.


>
> 5) Compile-time options need to be added to the prepocessor stuff defining
> the compile_opts string in src/config.c
>

I actually added this after the initial email in the git repository --
http://git.zx2c4.com/dnsmasq-ipset/ .


>
> Cheers,
>
> Simon.
>
> __**_
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss@lists.**thekelleys.org.uk
> http://lists.thekelleys.org.**uk/mailman/listinfo/dnsmasq-**discuss
>
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-16 Thread Jason A. Donenfeld
On Sat, Feb 16, 2013 at 5:28 PM, Mr Dash Four
 wrote:
> If the set is of type hash:net, then you can use "nomatch". In other words:

In an effort to prevent this thread from going off-topic, it's worth
noting that the hash:net functionality of ipset has nothing to do with
and does not replace the dnsmasq-ipset patches. It is very frequently
the case that it is not possible to know aprioi the IP ranges used by
a particular service, and instead the best way is via DNS lookup; see
prior emails for more detail.

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH 3/3] ipset: Update man page and example config to reflect new option.

2013-02-15 Thread Jason A. Donenfeld
---
 dnsmasq.conf.example | 4 
 man/dnsmasq.8| 6 ++
 2 files changed, 10 insertions(+)

diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example
index 5215c2a..9a0dbd7 100644
--- a/dnsmasq.conf.example
+++ b/dnsmasq.conf.example
@@ -69,6 +69,10 @@
 # --address (and --server) work with IPv6 addresses too.
 #address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
 
+# Add the IPs of all queries to yahoo.com, google.com, and their
+# subdomains to the vpn and search ipsets:
+#ipset=/yahoo.com/google.com/vpn,search
+
 # You can control how dnsmasq talks to a server: this forces
 # queries to 10.1.2.3 to be routed via eth1
 # server=10.1.2.3@eth1
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index b8dcfc7..941e84d 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -412,6 +412,12 @@ additional facility that /#/ matches any domain. Thus
 answered from /etc/hosts or DHCP and not sent to an upstream
 nameserver by a more specific --server directive.
 .TP
+.B --ipset=//[domain/][,]
+Places the resolved IP addresses of queries for the specified domains
+in the specified netfilter ip sets. Domains and subdomains are matched
+in the same way as --address. These ip sets must already exist. See
+ipset(8) for more details.
+.TP
 .B \-m, --mx-host=[[,],]
 Return an MX record named  pointing to the given hostname (if
 given), or
-- 
1.8.1.2


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH 1/3] ipset: Integrate ipset.c into build system.

2013-02-15 Thread Jason A. Donenfeld
Old kernels use HAVE_OLD_IPSET while newer kernels use HAVE_IPSET.
---
 Makefile  |   5 +-
 src/config.h  |   6 +++
 src/dnsmasq.h |   5 ++
 src/ipset.c   | 143 ++
 4 files changed, 157 insertions(+), 2 deletions(-)
 create mode 100644 src/ipset.c

diff --git a/Makefile b/Makefile
index c9cdb90..e0f6b90 100644
--- a/Makefile
+++ b/Makefile
@@ -59,13 +59,14 @@ ct_cflags =   `echo $(COPTS) | $(top)/bld/pkg-wrapper 
HAVE_CONNTRACK $(PKG_CONFI
 ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK 
$(PKG_CONFIG) --libs libnetfilter_conntrack`
 lua_cflags =  `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT 
$(PKG_CONFIG) --cflags lua5.1` 
 lua_libs =`echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT 
$(PKG_CONFIG) --libs lua5.1` 
+ipset_libs =  `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IPSET $(PKG_CONFIG) 
--libs libmnl`
 sunos_libs =  `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl 
-lposix4; fi`
 version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
 
 objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
-   dhcp-common.o outpacket.o radv.o slaac.o auth.o
+   dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
 
 hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h
@@ -74,7 +75,7 @@ all : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
  top="$(top)" \
  build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) 
$(lua_cflags)" \
- build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs)" \
+ build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(ipset_libs) 
$(sunos_libs)" \
  -f $(top)/Makefile dnsmasq 
 
 clean :
diff --git a/src/config.h b/src/config.h
index cff278d..3959b6c 100644
--- a/src/config.h
+++ b/src/config.h
@@ -97,6 +97,12 @@ HAVE_CONNTRACK
a build-dependency on libnetfilter_conntrack, but the resulting binary will
still run happily on a kernel without conntrack support.
 
+HAVE_IPSET
+HAVE_OLD_IPSET
+define this to include the ability to selectively add resolved ip addresses
+to given ipsets. HAVE_IPSET for Linux >= 2.6.32, and HAVE_OLD_IPSET for
+Linux >= 2.6.16 or >= 2.4.36.
+
 HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 21a309c..f1dffe8 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1117,6 +1117,11 @@ void emit_dbus_signal(int action, struct dhcp_lease 
*lease, char *hostname);
 #  endif
 #endif
 
+/* ipset.c */
+#if defined(HAVE_IPSET) || defined(HAVE_OLD_IPSET)
+int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, 
int remove);
+#endif
+
 /* helper.c */
 #if defined(HAVE_SCRIPT)
 int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
diff --git a/src/ipset.c b/src/ipset.c
new file mode 100644
index 000..b241ed4
--- /dev/null
+++ b/src/ipset.c
@@ -0,0 +1,143 @@
+/* ipset.c is Copyright (c) 2013 Jason A. Donenfeld . All 
Rights Reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dnsmasq.h"
+
+#if defined(HAVE_IPSET) || defined(HAVE_OLD_IPSET)
+#include 
+#include 
+#include 
+#include 
+#include 
+#if defined(HAVE_IPSET)
+#include 
+#include 
+#include 
+#endif
+#endif
+
+/* ipaddr should be either in_addr or in6_addr in network byte order.
+ * In other words, verbatium of what is in the DNS record. If remove
+ * is non-zero, the requested ipaddr is removed instead of added. */
+#if defined(HAVE_IPSET)
+int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, 
int remove)
+{
+   struct nlmsghdr *nlh;
+   struct nfgenmsg *nfg;
+   struct mnl_socket *mnl;
+   struct nlattr *nested[2];
+   char buffer[256];
+   int rc;
+   
+   rc = 0;
+
+   if (strlen(setname) >= IPSET_MAXNAMELEN) {
+   errno = ENAMETOOLONG;
+   return -1;
+   }
+   if (af != AF_INET && af != AF_INET6) {
+   errno = EAFNOSUPPORT;
+ 

[Dnsmasq-discuss] [PATCH 2/3] ipset: Parse new --ipset option and match domains in forward.c

2013-02-15 Thread Jason A. Donenfeld
The matching logic is the same as for --address. extract_address is
responsible for calling out to add_to_ipset.
---
 src/dnsmasq.h | 12 ++-
 src/forward.c | 20 ++-
 src/option.c  | 64 +++
 src/rfc1035.c | 14 -
 4 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f1dffe8..95bd464 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -430,6 +430,14 @@ struct server {
   struct server *next; 
 };
 
+#if defined(HAVE_IPSET) || defined(HAVE_OLD_IPSET)
+struct ipsets {
+  char **sets;
+  char *domain;
+  struct ipsets *next;
+};
+#endif
+
 struct irec {
   union mysockaddr addr;
   struct in_addr netmask; /* only valid for IPv4 */
@@ -779,6 +787,7 @@ extern struct daemon {
   struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
   struct bogus_addr *bogus_addr;
   struct server *servers;
+  struct ipsets *ipsets;
   int log_fac; /* log facility */
   char *log_file; /* optional log file */
   int max_logs;  /* queue limit */
@@ -903,7 +912,8 @@ size_t setup_reply(struct dns_header *header, size_t  qlen,
   struct all_addr *addrp, unsigned int flags,
   unsigned long local_ttl);
 int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
- time_t now, int is_sign, int checkrebind, int 
checking_disabled);
+ time_t now, char **ipsets, int is_sign, int checkrebind,
+ int checking_disabled);
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
   struct in_addr local_addr, struct in_addr local_netmask, 
time_t now);
 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char 
*name, 
diff --git a/src/forward.c b/src/forward.c
index fb0b4c4..ea0bdf4 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -439,9 +439,27 @@ static size_t process_reply(struct dns_header *header, 
time_t now,
struct server *server, size_t n, int check_rebind, 
int checking_disabled)
 {
   unsigned char *pheader, *sizep;
+  char **sets = 0;
   int munged = 0, is_sign;
   size_t plen; 
 
+#if defined(HAVE_IPSET) || defined(HAVE_OLD_IPSET)
+  /* Similar algorithm to search_servers. */
+  struct ipsets *ipset_pos;
+  unsigned int namelen = strlen(daemon->namebuff);
+  unsigned int matchlen = 0;
+  for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next) {
+ unsigned int domainlen = strlen(ipset_pos->domain);
+ char *matchstart = daemon->namebuff + namelen - domainlen;
+ if (namelen >= domainlen && hostname_isequal(matchstart, 
ipset_pos->domain) &&
+(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == 
'.' ) &&
+domainlen >= matchlen) {
+   matchlen = domainlen;
+   sets = ipset_pos->sets;
+ }
+  }
+#endif
+
   /* If upstream is advertising a larger UDP packet size
  than we allow, trim it so that we don't get overlarge
  requests for the client. We can't do this for signed packets. */
@@ -494,7 +512,7 @@ static size_t process_reply(struct dns_header *header, 
time_t now,
  SET_RCODE(header, NOERROR);
}
   
-  if (extract_addresses(header, n, daemon->namebuff, now, is_sign, 
check_rebind, checking_disabled))
+  if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, 
check_rebind, checking_disabled))
{
  my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), 
daemon->namebuff);
  munged = 1;
diff --git a/src/option.c b/src/option.c
index 3fc3e03..15fbd41 100644
--- a/src/option.c
+++ b/src/option.c
@@ -127,6 +127,7 @@ struct myoption {
 #define LOPT_AUTHSOA   316
 #define LOPT_AUTHSFS   317
 #define LOPT_AUTHPEER  318
+#define LOPT_IPSET 319
 
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
@@ -259,6 +260,7 @@ static const struct myoption opts[] =
 { "auth-soa", 1, 0, LOPT_AUTHSOA },
 { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
 { "auth-peer", 1, 0, LOPT_AUTHPEER }, 
+{ "ipset", 1, 0, LOPT_IPSET },
 { NULL, 0, 0, 0 }
   };
 
@@ -397,6 +399,7 @@ static struct {
   { LOPT_AUTHSOA, ARG_ONE, "[,...]", gettext_noop("Set authoritive 
zone information"), NULL },
   { LOPT_AUTHSFS, ARG_DUP, "[,...]", gettext_noop("Secondary 
authoritative nameservers for forward domains"), NULL },
   { LOPT_AUTHPEER, ARG_DUP, "[,...]", gettext_noop("Peers 
which are allowed to do zone transfer"), NULL },
+  { LOPT_IPSET, ARG_DUP, "//[,...]", 
gettext_noop("Specify ipsets to which matching domains should be added"), NULL 
},
   { 0, 0, NULL, NULL, NULL }
 }; 
 
@@ -2021,6 +2024,67 @@ static int one_opt(int option, char *arg, char *errstr, 
char *gen_err, int comma
daemon->servers = newlist;
break;
   }
+case LOPT_IPSET:
+#if !defined(HAVE_IPSET) && !defined(HAVE_OLD_IPS

[Dnsmasq-discuss] [PATCH 0/3] ipset: Add Netfilter IPSet Support do DNSMasq

2013-02-15 Thread Jason A. Donenfeld
Services like YouTube and Netflix use tons of ranges of IP addresses
that fluctuate wildly and aren't predictable. However, they're always
from a given subdomain using DNS, like *.c.youtube.com. I'd like to
have firewall rules for these IP addresses -- route them over this
interface, that interface, rate limit them like this, or that, etc. An
efficient way to do this is by adding IP addresses to a netfilter
ipset and using iptables' ipset match support. With services that use
lots of IPs spread out over ranges but instead use DNS, the only way
to do this is to have the DNS forwarder add the resolved IPs to an
ipset before returning the IP to the client.

This series of patches adds an --ipset option to dnsmasq which adds
resolved ips for specified domains to a given list of ipsets using the
netlink on newer kernels and setsockopt on older kernels.

--ipset=/google.com/yahoo.com/search,vpn

That option will add all resolved IPs for Google and Yahoo domains and
subdomains to two ipsets -- "search" and "vpn". (Sub)-domain matching is
conducted in the same way as with --address.

--ipset=resolved
--ipset=/#/resolved

These two options are identical. They each add all resolved domains to
the "resolved" ipset.

If this mailing list post becomes stale, the latest series of patches
may be found at <http://git.zx2c4.com/dnsmasq-ipset>.

Jason A. Donenfeld (3):
  ipset: Integrate ipset.c into build system.
  ipset: Parse new --ipset option and match domains in forward.c
  ipset: Update man page and example config to reflect new option.

 Makefile |   5 +-
 dnsmasq.conf.example |   4 ++
 man/dnsmasq.8|   6 +++
 src/config.h |   6 +++
 src/dnsmasq.h|  17 +-
 src/forward.c|  20 ++-
 src/ipset.c  | 143 +++
 src/option.c |  64 +++
 src/rfc1035.c|  14 -
 9 files changed, 274 insertions(+), 5 deletions(-)
 create mode 100644 src/ipset.c

-- 
1.8.1.2


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] [PATCH] Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
Hah, forget that. I just wrote the entire thing, including configuration,
and it works great. I'll send full patches to the mailing list shortly.
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


[Dnsmasq-discuss] [PATCH] Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
Hi Simon,

Another update to reduce the amount of work for you. This thread
should supersede the other one.

I made ipset.c a bit nicer for dnsmasq by using struct all_addr. New
patch to replace all old ones:

View: 
http://git.zx2c4.com/dnsmasq-ipset/commit/?id=b93018649a533a341b724e3323011714a84d5ef0
Patch: 
http://git.zx2c4.com/dnsmasq-ipset/patch/?id=b93018649a533a341b724e3323011714a84d5ef0


I added some sample code for where it could be successfully integrated
with a simple /* TODO */ that should be filled out with the server
lookup / matching logic, which I'll leave to you:

View: 
http://git.zx2c4.com/dnsmasq-ipset/commit/?id=954a63cda0fa08e5ed0f18a81a226669c3dc5039
Patch: 
http://git.zx2c4.com/dnsmasq-ipset/patch/?id=954a63cda0fa08e5ed0f18a81a226669c3dc5039

If I do further work on this, the code will be found at:
http://git.zx2c4.com/dnsmasq-ipset/


Looking forward.

Jason

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
On Fri, Feb 15, 2013 at 11:30 PM, John Brendler  wrote:
> I use ipsets and have written scripts for handling them dynamically.
> I think this is a very interesting idea.  I'd benefit from hearing some
> elaboration on the use cases you have in mind.  I think this might also
> help Simon understand how best to integrate.

Sure. There are some decent examples on
. Check out the "Why?" section
as well as the sample script.

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
Simon,

The attached patch wires ipset into the dnsmasq build system. I'm
assuming the integration and config syntax is something you want to do
yourself rather than have me do it.

After applying the patch, you will be able to call:

int add_to_ipset(const char *setname, const void *ipaddr, int af, int remove);

Hope this helps!

Jason


0001-Wire-up-ipset-to-build-system.patch
Description: Binary data
___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
On Fri, Feb 15, 2013 at 10:42 PM, sven falempin  wrote:
> Previsouly i propose a patch to filter out some domain,
> i understand filtering should be done by iptables, but only if you think
> linux.
>
> Is it possible to use a version of this code to filter some domain out
> and/or to allow just a subset of domains ?

I'm sure it's possible to warp ipset to do all sorts of things for
you. It's pretty generic and flexible.

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


Re: [Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-15 Thread Jason A. Donenfeld
Hi Simon,

On Fri, Feb 15, 2013 at 3:05 PM, Simon Kelley  wrote:
> It looks like the extra code is quite small, so I'd certainly consider
> it.

Wonderful! I've extracted heavy lifting code into a separate file
(attached as ipset.c), and licensed it under the same license as
dnsmasq so that you can just copy and paste. Given that the
server=/.../ matching already exists and that the difficult netlink
part has already been written, adding this to dnsmasq should be very
trivial.

> Do you take account of the time-to-live of DNS records, or are
> ipsets create-only?

IPs can be both added and removed to and from ipsets. Ipset itself
doesn't have a built-in TTL mechanism, but it would be trivial to just
remove IPs from the ipset at the sametime dnsmasq purges its cache.
This isn't always the desired behavior, however -- if I have connected
to an IP address that was added to an ipset via its DNS lookup, I
don't want it to be removed from the ipset while I'm still connected
to it, even if the DNS TTL is up. In any case, I've added a "remove"
argument to the ipset function so that you can easily add this
functionality behind a switch.

Looking forward! Thanks Simon.

Jason
/* ipset.c: add or remove an ip address to an ipset.
 * 
 * Copyright (C) 2013 Jason A. Donenfeld . All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 dated June, 1991, or
 *  (at your option) version 3 dated 29 June, 2007.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *   
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For Linux >= 2.6.32, compile with -lmnl. For Linux >= 2.6.16 or >= 2.4.36, compile with -DOLD_IPSET.
 */

#include 
#include 
#include 
#include 
#include 
#ifndef OLD_IPSET
#include 
#include 
#include 
#endif

/* ipaddr should be either in_addr or in6_addr in network byte order.
 * In other words, verbatium of what is in the DNS record. If remove
 * is non-zero, the requested ipaddr is removed instead of added. */
int add_to_ipset(const char *setname, const void *ipaddr, int af, int remove)
{
#ifndef OLD_IPSET
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfg;
	struct mnl_socket *mnl;
	struct nlattr *nested[2];
	char buffer[256];
	ssize_t received;
	int port, rc;
	
	rc = 0;

	if (strlen(setname) >= IPSET_MAXNAMELEN) {
		errno = ENAMETOOLONG;
		return -1;
	}
	if (af != AF_INET && af != AF_INET6) {
		errno = EAFNOSUPPORT;
		return -1;
	}

	nlh = mnl_nlmsg_put_header(buffer);
	nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
	nlh->nlmsg_flags = NLM_F_REQUEST;

	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
	nfg->nfgen_family = af;
	nfg->version = NFNETLINK_V0;
	nfg->res_id = htons(0);

	mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
	mnl_attr_put(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
	nested[0] = mnl_attr_nest_start(nlh, IPSET_ATTR_DATA);
	nested[1] = mnl_attr_nest_start(nlh, IPSET_ATTR_IP);
	mnl_attr_put(nlh, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6)
			| NLA_F_NET_BYTEORDER, (af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)), ipaddr);
	mnl_attr_nest_end(nlh, nested[1]);	
	mnl_attr_nest_end(nlh, nested[0]);

	mnl = mnl_socket_open(NETLINK_NETFILTER);
	if (mnl <= 0)
		return -1;
	if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
		rc = -1;
		goto close;
	}
	if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
		rc = -1;
		goto close;
	}
close:
	mnl_socket_close(mnl);
	return rc;
#else
	int sock, rc;
	socklen_t size;
	struct ip_set_req_adt_get {
		unsigned op;
		unsigned version;
		union {
			char name[32];
			uint16_t index;
		} set;
		char typename[32];
	} req_adt_get;
	struct ip_set_req_adt {
		unsigned op;
		uint16_t index;
		uint32_t ip;
	} req_adt;
	
	rc = 0;
	
	if (strlen(setname) >= sizeof(req_adt_get.set.name)) {
		errno = ENAMETOOLONG;
		return -1;
	}
	if (af != AF_INET) {
		errno = EAFNOSUPPORT;
		return -1;
	}
	
	sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	if (sock < 0)
		return -1;
	
	req_adt_get.op = 0x10;
	req_adt_get.version = 3;
	strcpy(req_adt_get.set.name, setname);
	size = sizeof(req_adt_get);
	if (getsockopt(sock, SOL_IP, 83, &req_adt_get, &size) < 0) {
		rc = -1;
		goto close;
	}
	req_adt.op = remove ? 0x102 : 0x101;
	req_adt.index = req_adt_get.set.index;
	req_adt.ip = ntohl(*(uint32_t *)ipaddr);
	if (setsockopt(sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0) {
		rc = -1;
		

[Dnsmasq-discuss] ipset-dns: Integrate Netfilter IPSet Support

2013-02-14 Thread Jason A. Donenfeld
Hi Simon & Crew,

Services like YouTube and Netflix use tons of ranges of IP addresses
that fluctuate wildly and aren't predictable. However, they're always
from a given subdomain using DNS, like *.c.youtube.com. I'd like to
have firewall rules for these IP addresses -- route them over this
interface, that interface, rate limit them like this, or that, etc. An
efficient way to do this is by adding IP addresses to a netfilter
ipset and using iptables' ipset match support. With services that use
lots of IPs spread out over ranges but instead use DNS, the only way
to do this is to have the DNS forwarder add the resolved IPs to an
ipset before returning the IP to the client.

I've written ipset-dns, a super trivial DNS forwarder that's meant to
be plugged into dnsmasq's server=/.../ directive.

http://git.zx2c4.com/ipset-dns/about/

But forwarding one forwarder to another forwarder is ugly, and ideally
this functionality would just be plugged directly into dnsmasq:

dnsmasq.conf:

ipset=/c.youtube.com/netflix.com/vpnset

This would add all the IPs returned for those queries to the provided
ipset (vpnset in this case).

Is there much interest in this feature? Is it something you'd consider adding?

Thanks,
Jason Donenfeld

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss