dnsproxy-master/0000755000000000000000000000000014151175173012740 5ustar rootrootdnsproxy-master/dnsproxy.c0000644000000000000000000002373614151175173015005 0ustar rootroot/* * Copyright (c) 2003,2004,2005,2010,2016 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #define GLOBALS 1 #include "dnsproxy.h" #define RD(x) (*(x + 2) & 0x01) static unsigned short queryid = 0; #define QUERYID queryid++ static struct sockaddr_in authoritative_addr; static struct sockaddr_in recursive_addr; static int sock_query; static int sock_answer; static int dnsproxy_sig; extern int event_gotsig; extern int (*event_sigcb)(void); #ifdef DEBUG char *malloc_options = "AGZ"; #endif /* signal_handler -- Called by libevent if a signal arrives. */ void signal_handler(int sig, short event, void *arg) { (void)event_loopexit(NULL); fatal("exiting on signal %d", sig); } /* timeout -- Called by the event loop when a query times out. Removes the * query from the queue. */ /* ARGSUSED */ static void timeout(int fd, short event, void *arg) { hash_remove_request((struct request *)arg); free((struct request *)arg); ++removed_queries; } /* do_query -- Called by the event loop when a packet arrives at our * listening socket. Read the packet, create a new query, append it to the * queue and send it to the correct server. */ /* ARGSUSED */ static void do_query(int fd, short event, void *arg) { char buf[MAXEDNS]; int byte = 0; struct sockaddr_in fromaddr; unsigned int fromlen = sizeof(fromaddr); struct request *req; struct timeval tv; ++all_queries; /* Reschedule event */ event_add((struct event *)arg, NULL); /* read packet from socket */ if ((byte = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&fromaddr, &fromlen)) == -1) { error("recvfrom failed: %s", strerror(errno)); ++dropped_queries; return; } /* check for minimum dns packet length */ if (byte < 12) { error("query too short from %s", inet_ntoa(fromaddr.sin_addr)); ++dropped_queries; return; } /* allocate new request */ if ((req = calloc(1, sizeof(struct request))) == NULL) { error("calloc: %s", strerror(errno)); ++dropped_queries; return; } /* fill the request structure */ req->id = QUERYID; memcpy(&req->client, &fromaddr, sizeof(struct sockaddr_in)); memcpy(&req->clientid, &buf[0], 2); /* where is this query coming from? */ if (is_internal(fromaddr.sin_addr)) { req->recursion = RD(buf); DPRINTF(("Internal query RD=%d\n", req->recursion)); } else { /* no recursion for foreigners */ req->recursion = 0; DPRINTF(("External query RD=%d\n", RD(buf))); } /* insert it into the hash table */ hash_add_request(req); /* overwrite the original query id */ memcpy(&buf[0], &req->id, 2); if (req->recursion) { /* recursive queries timeout in 90s */ event_set(&req->timeout, -1, 0, timeout, req); tv.tv_sec=recursive_timeout; tv.tv_usec=0; event_add(&req->timeout, &tv); /* send it to our recursive server */ if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, (struct sockaddr *)&recursive_addr, sizeof(struct sockaddr_in))) == -1) { error("sendto failed: %s", strerror(errno)); ++dropped_queries; return; } ++recursive_queries; } else { /* authoritative queries timeout in 10s */ event_set(&req->timeout, -1, 0, timeout, req); tv.tv_sec=authoritative_timeout; tv.tv_usec=0; event_add(&req->timeout, &tv); /* send it to our authoritative server */ if ((byte = sendto(sock_answer, buf, (unsigned int)byte, 0, (struct sockaddr *)&authoritative_addr, sizeof(struct sockaddr_in))) == -1) { error("sendto failed: %s", strerror(errno)); ++dropped_queries; return; } ++authoritative_queries; } } /* do_answer -- Process a packet coming from our authoritative or recursive * server. Find the corresponding query and send answer back to querying * host. */ /* ARGSUSED */ static void do_answer(int fd, short event, void *arg) { char buf[MAXEDNS]; int byte = 0; struct request *query = NULL; /* Reschedule event */ event_add((struct event *)arg, NULL); /* read packet from socket */ if ((byte = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL)) == -1) { error("recvfrom failed: %s", strerror(errno)); ++dropped_answers; return; } /* check for minimum dns packet length */ if (byte < 12) { error("answer too short"); ++dropped_answers; return; } /* find corresponding query */ if ((query = hash_find_request(*((unsigned short *)&buf))) == NULL) { ++late_answers; return; } event_del(&query->timeout); hash_remove_request(query); /* restore original query id */ memcpy(&buf[0], &query->clientid, 2); /* send answer back to querying host */ if (sendto(sock_query, buf, (unsigned int)byte, 0, (struct sockaddr *)&query->client, sizeof(struct sockaddr_in)) == -1) { error("sendto failed: %s", strerror(errno)); ++dropped_answers; } else ++answered_queries; free(query); } /* main -- dnsproxy main function */ int main(int argc, char *argv[]) { int ch; struct passwd *pw = NULL; struct sockaddr_in addr; struct event evq, eva; struct event evsigint, evsigterm, evsighup; const char *config = "/etc/dnsproxy.conf"; int daemonize = 0; /* Process commandline arguments */ while ((ch = getopt(argc, argv, "c:dhV")) != -1) { switch (ch) { case 'c': config = optarg; break; case 'd': daemonize = 1; break; case 'V': fprintf(stderr, PACKAGE_STRING "\n"); exit(0); /* FALLTHROUGH */ case 'h': default: fprintf(stderr, "usage: dnsproxy [-c file] [-dhV]\n" \ "\t-c file Read configuration from file\n" \ "\t-d Detach and run as a daemon\n" \ "\t-h This help text\n" \ "\t-V Show version information\n"); exit(1); } } /* Parse configuration and check required parameters */ if (!parse(config)) fatal("unable to parse configuration"); if (!authoritative || !recursive) fatal("No authoritative or recursive server defined"); if (!listenat) listenat = strdup("0.0.0.0"); /* Create and bind query socket */ if ((sock_query = socket(AF_INET, SOCK_DGRAM, 0)) == -1) fatal("unable to create socket: %s", strerror(errno)); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_addr.s_addr = inet_addr(listenat); addr.sin_port = htons(port); addr.sin_family = AF_INET; if (bind(sock_query, (struct sockaddr *)&addr, sizeof(addr)) != 0) fatal("unable to bind socket: %s", strerror(errno)); /* Create answer socket */ if ((sock_answer = socket(AF_INET, SOCK_DGRAM, 0)) == -1) fatal("unable to create socket: %s", strerror(errno)); /* Fill sockaddr_in structs for both servers */ memset(&authoritative_addr, 0, sizeof(struct sockaddr_in)); authoritative_addr.sin_addr.s_addr = inet_addr(authoritative); authoritative_addr.sin_port = htons(authoritative_port); authoritative_addr.sin_family = AF_INET; memset(&recursive_addr, 0, sizeof(struct sockaddr_in)); recursive_addr.sin_addr.s_addr = inet_addr(recursive); recursive_addr.sin_port = htons(recursive_port); recursive_addr.sin_family = AF_INET; /* Daemonize if requested and switch to syslog */ if (daemonize) { if (daemon(0, 0) == -1) fatal("unable to daemonize"); log_syslog("dnsproxy"); } /* Find less privileged user */ if (user) { pw = getpwnam(user); if (!pw) fatal("unable to find user %s", user); } /* Do a chroot if requested */ if (chrootdir) { if (chroot(chrootdir) == -1) fatal("unable to chroot to %s", chrootdir); if (chdir("/") == -1) fatal("unable to chdir"); } /* Drop privileges */ if (user) { if (setgroups(1, &pw->pw_gid) < 0) fatal("setgroups: %s", strerror(errno)); #if defined(HAVE_SETRESGID) if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) fatal("setresgid: %s", strerror(errno)); #elif defined(HAVE_SETREGID) if (setregid(pw->pw_gid, pw->pw_gid) < 0) fatal("setregid: %s", strerror(errno)); #else if (setegid(pw->pw_gid) < 0) fatal("setegid: %s", strerror(errno)); if (setgid(pw->pw_gid) < 0) fatal("setgid: %s", strerror(errno)); #endif #if defined(HAVE_SETRESUID) if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) fatal("setresuid: %s", strerror(errno)); #elif defined(HAVE_SETREUID) if (setreuid(pw->pw_uid, pw->pw_uid) < 0) fatal("setreuid: %s", strerror(errno)); #else if (seteuid(pw->pw_uid) < 0) fatal("seteuid: %s", strerror(errno)); if (setuid(pw->pw_uid) < 0) fatal("setuid: %s", strerror(errno)); #endif } event_init(); /* Take care of signals */ signal_set(&evsigint, SIGINT, signal_handler, NULL); signal_set(&evsigterm, SIGTERM, signal_handler, NULL); signal_set(&evsighup, SIGHUP, signal_handler, NULL); signal_add(&evsigint, NULL); signal_add(&evsigterm, NULL); signal_add(&evsighup, NULL); /* Zero counters and start statistics timer */ statistics_start(); /* Install query and answer event handlers */ event_set(&evq, sock_query, EV_READ, do_query, &evq); event_set(&eva, sock_answer, EV_READ, do_answer, &eva); event_add(&evq, NULL); event_add(&eva, NULL); /* Start libevent main loop */ event_dispatch(); return 0; } dnsproxy-master/dnsproxy.conf0000644000000000000000000000124014151175173015472 0ustar rootroot# # dnsproxy 1.15 configuration file example # # # Authoritative server # authoritative 127.0.0.1 authoritative-port 53001 # It's port. Defaults to 53. authoritative-timeout 10 # Seconds to wait for answers. # # Recursive resolver # recursive 127.0.0.1 recursive-port 53002 # It's port. Defaults to 53. recursive-timeout 90 # Seconds to wait for answers. # # Local address and port of dnsproxy # listen 192.168.168.1 port 53000 # # Security features # chroot /var/empty user nobody # # Internal networks (allowed to do recursive queries) # internal 192.168.168.0/24 # Our internal network internal 192.168.169.0/24 # Friendly neighbours internal 127.0.0.1 dnsproxy-master/dnsproxy.8.in0000644000000000000000000001205114151175173015323 0ustar rootroot.\" .\" Copyright (c) 2003,2004 Armin Wolfermann .\" .\" Permission is hereby granted, free of charge, to any person obtaining a .\" copy of this software and associated documentation files (the "Software"), .\" to deal in the Software without restriction, including without limitation .\" the rights to use, copy, modify, merge, publish, distribute, sublicense, .\" and/or sell copies of the Software, and to permit persons to whom the .\" Software is furnished to do so, subject to the following conditions: .\" .\" The above copyright notice and this permission notice shall be included in .\" all copies or substantial portions of the Software. .\" .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL .\" THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING .\" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER .\" DEALINGS IN THE SOFTWARE. .\" .Dd November 29, 2003 .Dt DNSPROXY 8 .Os LOCAL .Sh NAME .Nm dnsproxy .Nd DNS proxy .Sh SYNOPSIS .Nm dnsproxy .Op Fl dhV .Op Fl c Ar file .\" ------------------------------------------------------------------ .Sh DESCRIPTION .\" ------------------------------------------------------------------ The .Nm daemon waits for nameserver queries on a user specified address, dispatches these queries to authoritative and recursive nameservers and forwards the received answers back to the original client. .Pp The options are as follows: .Bl -tag -width Dfxfile .It Fl c Ar file Read configuration from file. .It Fl d Detach from current terminal and run as background process. .It Fl h Show usage. .It Fl V Show version. .El .Pp If a client from an internal IP address does a recursive lookup the query is forwarded to a recursive DNS server. Authoritative queries and queries coming from clients in foreign networks are forwarded to an authoritative DNS server. .Pp .\" ------------------------------------------------------------------ .Sh CONFIGURATION FILE .\" ------------------------------------------------------------------ At startup .Nm reads a configuration file specified via the -c option or at the default location of /etc/dnsproxy.conf. .Pp The following keywords are recognized: .Bl -ohang .It authoritative Ar IP Address of the authoritative nameserver [required]. .It recursive Ar IP Address of the recursive nameserver [required]. .It listen Ar IP Local address (defaults to 0.0.0.0). .It port Ar number Local port number (defaults to 53). .It chroot Ar path A path to chroot to before starting to answer queries. .It user Ar name A user to change to before starting to answer queries. .It authoritative-timeout Ar seconds Time in seconds when authoritative queries time out (defaults to 10). .It recursive-timeout Ar seconds Time in seconds when recursive queries time out (defaults to 90). .It authoritative-port Ar number Port number on authoritative nameserver (defaults to 53). .It recursive-port Ar number Port number on recursive nameserver (defaults to 53). .It statistics Ar seconds Period between output of statistics (defaults to 3600). Use 0 to disable output of statistics completely. .It internal Fa network Declare networks recognized as internal and thus eligible to do recursive queries. One network in CIDR notation per keyword. .El .Ss EXAMPLE .Bd -literal -offset indent authoritative 10.1.1.1 recursive 127.0.0.1 recursive-port 10053 listen 192.168.1.1 port 53 chroot /var/empty user nobody internal 192.168.1.0/24 internal 127.0.0.1 .Ed .Pp .\" ------------------------------------------------------------------ .Sh STATISTICS .\" ------------------------------------------------------------------ Every hour (by default) .Nm logs the collected statistics about its usage to standard error (or syslog when running detached). Statistics look like .Bd -literal -offset indent ActiveQr AuthorQr RecursQr AllQuery Answered 0 0 0 0 0 TimeoutQ DroppedQ DroppedA LateAnsw HashColl 0 0 0 0 0 .Ed .Pp and have the following meaning: .Bl -ohang .It ActiveQr Number of currently active queries proxied to the servers. .It AuthorQr Accumulated number of authoritative queries. .It RecursQr Accumulated number of recursive queries. .It AllQuery Accumulated number of all queries ever received. .It Answered Accumulated number of answered queries. .It TimeoutQ Accumulated number of queries that did not receive an answer in time. .It DroppedQ Accumulated number of dropped queries (e.g. transmission errors). .It DroppedA Accumulated number of dropped answers. .It LateAnsw Accumulated number of answers received after the timeout period. .It HashColl Accumulated number of hash collisions in the query list. .El .\" .Sh SEE ALSO .Xr named 8 .Sh VERSION This manual page describes .Nm version @PACKAGE_VERSION@. .Sh AUTHORS Armin Wolfermann .Pp The .Nm homepage is at http://www.wolfermann.org/dnsproxy.html. .Pp dnsproxy-master/bootstrap0000755000000000000000000000021314151175173014677 0ustar rootroot#!/bin/sh export AUTOCONF_VERSION=2.69 export AUTOMAKE_VERSION=1.15 autoreconf -fi && echo "Bootstrapped successfully. Now run configure." dnsproxy-master/NEWS0000644000000000000000000000000014151175173013425 0ustar rootrootdnsproxy-master/configure.ac0000644000000000000000000001116414151175173015231 0ustar rootrootAC_INIT(dnsproxy, 1.17) AC_PREREQ(2.60) AC_CONFIG_HEADERS(config.h) AM_INIT_AUTOMAKE dnl ------------------------------------------------------------------ dnl Check for programs dnl ------------------------------------------------------------------ AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_MAKE_SET AC_CACHE_SAVE dnl ------------------------------------------------------------------ dnl Check for headers dnl ------------------------------------------------------------------ AC_USE_SYSTEM_EXTENSIONS AC_C_CONST AC_HEADER_STDC AC_HEADER_TIME AC_CHECK_HEADERS(sys/types.h sys/socket.h sys/time.h) AC_CHECK_HEADERS(netinet/in.h arpa/inet.h) AC_CHECK_HEADERS(errno.h syslog.h) AC_TYPE_SIGNAL AC_CACHE_SAVE dnl ------------------------------------------------------------------ dnl Check for functions dnl ------------------------------------------------------------------ AC_CHECK_FUNCS(strchr memcpy) AC_CHECK_FUNCS(setregid setresgid setresuid setreuid) AC_CACHE_SAVE dnl ------------------------------------------------------------------ dnl Check for additional libraries dnl ------------------------------------------------------------------ AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([socket], [socket], [], [ AC_CHECK_LIB([socket], [socket], [LIBS="-lsocket -lnsl $LIBS"], [], [-lnsl]) ]) AC_CACHE_SAVE dnl ------------------------------------------------------------------ dnl Enable extended warnings while developing dnl ------------------------------------------------------------------ AC_ARG_ENABLE(warnings, [ AC_HELP_STRING([--enable-warnings], [enable all sorts of warnings for debugging])], [ CFLAGS="${CFLAGS} -Wall -Werror -Wcast-qual -Wmissing-declarations \ -W -Wmissing-prototypes -Wnested-externs -Wshadow \ -Wwrite-strings -Wno-unused -Wno-sign-compare" ]) AC_SUBST(CFLAGS) dnl ------------------------------------------------------------------ dnl Maximum EDNS packet size dnl ------------------------------------------------------------------ AC_ARG_ENABLE([edns], [ AC_HELP_STRING([--enable-edns=N], [maximum EDNS packet size (default is 4096)])], [], [enable_edns=4096]) AS_IF([test $enable_edns = no], [enable_edns=4096]) AC_DEFINE_UNQUOTED([MAXEDNS],[$enable_edns],[Maximum EDNS packet size]) dnl ------------------------------------------------------------------ dnl Check for libevent library dnl ------------------------------------------------------------------ lefound="no" LIBS="$LIBS -levent" AC_MSG_CHECKING(for libevent) AC_ARG_WITH(libevent, AC_HELP_STRING( [--with-libevent=PATH], [directory prefix where libevent is found] ), [ if test -f $withval/include/event.h; then CFLAGS="${CFLAGS} -I$withval/include" elif test -f $withval/event.h; then CFLAGS="${CFLAGS} -I$withval" else AC_ERROR([event.h not found]) fi if test -f $withval/lib; then LDFLAGS="${LDFLAGS} -L$withval/lib" else LDFLAGS="${LDFLAGS} -L$withval" fi AC_MSG_RESULT([using $withval]) lefound="yes" ], [ saved_CFLAGS=$CFLAGS saved_LDFLAGS=$LDFLAGS for testdir in "" $prefix /usr/local /opt/csw; do if test -z "$testdir"; then CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" else CFLAGS="$saved_CFLAGS -I$testdir/include" LDFLAGS="$saved_LDFLAGS -L$testdir/lib" fi AC_TRY_LINK([#include #include #include ], [ event_init(); ], [ lefound="$testdir" ], [ lefound="no" ]) if test "$lefound" != "no"; then if test -z "$testdir"; then AC_MSG_RESULT([found]) else AC_MSG_RESULT([found in $lefound]) fi break fi done ] ) if test "$lefound" = "no"; then AC_MSG_ERROR([ This software requires the libevent library available at http://libevent.org/ You may specify it's directory prefix with ./configure --with-libevent=/prefix/of/libevent ]) fi dnl ------------------------------------------------------------------ dnl Check for available nroff and manpage macro package dnl ------------------------------------------------------------------ AC_PATH_PROGS([NROFF], [nroff awf], [/bin/false], [$PATH:/usr/ucb]) if ${NROFF} -mdoc dnsproxy.8 >/dev/null 2>&1; then MAN=mdoc else MAN=man fi AC_SUBST(MAN) dnl ------------------------------------------------------------------ dnl Generate Makefile by default. Others only if their .in file dnl exists in the current directory, which happens in my workdir dnl but not for distributed tarballs. dnl ------------------------------------------------------------------ AC_CONFIG_FILES(Makefile) if test -r "dnsproxy.8.in"; then AC_CONFIG_FILES(dnsproxy.8) fi AC_OUTPUT() AC_MSG_RESULT() AC_MSG_RESULT([Configured successfully. Now run make.]) AC_MSG_RESULT() dnsproxy-master/COPYING0000777000000000000000000000000014152542404014771 2LICENSEustar rootrootdnsproxy-master/AUTHORS0000644000000000000000000000000014151175173013776 0ustar rootrootdnsproxy-master/LICENSE0000644000000000000000000000211214151175173013741 0ustar rootrootMIT License Copyright (c) 2003,2004,2005,2010,2016,2017 Armin Wolfermann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. dnsproxy-master/README0000777000000000000000000000000014152542404015070 2README.mdustar rootrootdnsproxy-master/hash.c0000644000000000000000000000356614151175173014041 0ustar rootroot/* * Copyright (c) 2003,2004 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "dnsproxy.h" #define HASHSIZE 10 #define HASH(id) (id & ((1 << HASHSIZE) - 1)) static struct request *request_hash[1 << HASHSIZE]; void hash_add_request(struct request *req) { struct request **p = &request_hash[HASH(req->id)]; if ((req->next = *p) != NULL) { (*p)->prev = &req->next; ++hash_collisions; } *p = req; req->prev = p; ++active_queries; } void hash_remove_request(struct request *req) { if (!req->prev) return; if (req->next) req->next->prev = req->prev; *req->prev = req->next; req->prev = NULL; --active_queries; } struct request * hash_find_request(unsigned short id) { struct request *req = request_hash[HASH(id)]; for (;;) { if (!req) break; if (req->id == id) break; req = req->next; } return req; } dnsproxy-master/daemon.c0000644000000000000000000000422314151175173014350 0ustar rootroot/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * From: $OpenBSD: daemon.c,v 1.5 2003/07/15 17:32:41 deraadt Exp $ */ #include #include #include #include #include "dnsproxy.h" int daemon(int nochdir, int noclose) { int fd; switch (fork()) { case -1: return (-1); case 0: break; default: _exit(0); } if (setsid() == -1) return (-1); if (!nochdir) (void)chdir("/"); if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > 2) (void)close (fd); } return (0); } dnsproxy-master/.github/0000755000000000000000000000000014151175173014300 5ustar rootrootdnsproxy-master/.github/workflows/0000755000000000000000000000000014151175173016335 5ustar rootrootdnsproxy-master/.github/workflows/build.yml0000644000000000000000000000117114151175173020157 0ustar rootrootname: build-check on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: install_dependencies run: sudo apt update && sudo apt install libevent-dev - name: build_dist_distclean run: | ./bootstrap ./configure make make dist ls dnsproxy-[0-9]*.tar.gz make distclean - name: build_install_run run: | ./bootstrap ./configure make sudo make install dnsproxy -V dnsproxy -h 2>&1 | egrep -iC10 usage dnsproxy-master/stats.c0000644000000000000000000000404614151175173014246 0ustar rootroot/* * Copyright (c) 2003,2004 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include "dnsproxy.h" static struct event timeout; static struct timeval tv; /* ARGSUSED */ static void statistics_timeout(int fd, short event, void *arg) { /* reschedule timer event */ if (event_add(&timeout, &tv) == -1) fatal("event_add: %s", strerror(errno)); /* print statistics */ info("ActiveQr AuthorQr RecursQr AllQuery Answered"); info("%8ld %8ld %8ld %8ld %8ld", active_queries, authoritative_queries, recursive_queries, all_queries, answered_queries); info("TimeoutQ DroppedQ DroppedA LateAnsw HashColl"); info("%8ld %8ld %8ld %8ld %8ld", removed_queries, dropped_queries, dropped_answers, late_answers, hash_collisions); } void statistics_start(void) { if (stats_timeout > 0) { tv.tv_sec=stats_timeout; tv.tv_usec=0; evtimer_set(&timeout, statistics_timeout, NULL); if (evtimer_add(&timeout, &tv) == -1) fatal("evtimer_add: %s", strerror(errno)); } } dnsproxy-master/README.md0000644000000000000000000000571114151175173014223 0ustar rootroot#### DESCRIPTION The dnsproxy daemon is a proxy for DNS queries. It forwards these queries to two previously configured nameservers: one for authoritative queries and another for recursive queries. The received answers are sent back to the client unchanged. No local caching is done and only UDP queries are supported. Primary motivation for this project was the need to replace Bind servers with djbdns in an ISP environment. These servers got recursive queries from customers and authoritative queries from outside at the same IP address. Now it was possible to run dnscache and tinydns on the same machine with queries dispatched by dnsproxy. Other scenarios are firewalls where you want to proxy queries to the real servers in your DMZ. Or internal nameservers behind firewalls, or... Some features: - Secure. Runs chrooted and without root privileges. - Fast. Able to process hundreds of queries per second. - Easy to setup. Simple configuration file. #### INSTALLATION If you run any current UNIX-like operating system, only the following steps should be necessary: ``` ./configure make make install ``` Unlike earlier releases this release does not include the libevent library. It should now also be available from your operating systems ports/packages/rpm/deb repository or as always from the source at http://libevent.org/. If it is not found by the configure script you may specify the directory prefix of your libevent installation with: ``` ./configure --with-libevent=/usr/local ``` #### CONFIGURATION At startup dnsproxy reads a configuration file specified via the -c option or at the default location of /etc/dnsproxy.conf. The syntax of this configuration file is of the form "keyword value" and looks like: ``` authoritative 127.0.0.1 # Authoritative server. Required. authoritative-port 53001 # It's port. Defaults to 53. authoritative-timeout 10 # Seconds to wait for answers. recursive 127.0.0.1 # Recursive server. Required. recursive-port 53002 # It's port. Defaults to 53. recursive-timeout 90 # Seconds to wait for answers. listen 192.168.168.1 # Dnsproxy's listen address. port 53 # Dnsproxy's port address. chroot /var/empty # Directory to chroot dnsproxy. user nobody # Unprivileged user to run as. internal 192.168.168.0/24 # Only internal IP addresses are internal 127.0.0.1 # allowed to do recursive queries. statistics 3600 # Print statistics every hour. ``` #### COMPATIBILITY This package should build and run on OpenBSD, FreeBSD, Solaris, Linux. Other POSIX environments should work also. Please drop me a mail if you run dnsproxy on an unlisted system. #### LICENSE This software is released under an OSI approved MIT-style license. dnsproxy-master/parse.c0000644000000000000000000000545714151175173014231 0ustar rootroot/* * Copyright (c) 2003,2004 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include "dnsproxy.h" /* parse -- Simple configuration file parser. Takes a filename and * reads pairs of 'key value' or 'key = value'. */ int parse(const char *fname) { FILE *f; char buf[1024]; char *s, *key, *arg; if ((f = fopen(fname, "r")) == NULL) return 0; while (fgets(buf, sizeof(buf), f) != NULL) { if ((s = strchr(buf, '#')) != NULL) *s = '\0'; key = strtok(buf, " \t="); arg = strtok(NULL, " \t\n"); if (!key || !arg) continue; DPRINTF(("Found key '%s' arg '%s'\n", key, arg)); if (!strcmp(key, "authoritative")) { authoritative = strdup(arg); continue; } if (!strcmp(key, "authoritative-timeout")) { authoritative_timeout = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "authoritative-port")) { authoritative_port = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "recursive")) { recursive = strdup(arg); continue; } if (!strcmp(key, "recursive-timeout")) { recursive_timeout = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "recursive-port")) { recursive_port = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "statistics")) { stats_timeout = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "listen")) { listenat = strdup(arg); continue; } if (!strcmp(key, "port")) { port = strtol(arg, NULL, 10); continue; } if (!strcmp(key, "chroot")) { chrootdir = strdup(arg); continue; } if (!strcmp(key, "user")) { user = strdup(arg); continue; } if (!strcmp(key, "internal")) { add_internal(arg); continue; } info("Unable to parse '%s'", buf); } fclose(f); return 1; } dnsproxy-master/ChangeLog0000644000000000000000000000000014151175173014500 0ustar rootrootdnsproxy-master/internal.c0000644000000000000000000000446414151175173014730 0ustar rootroot/* * Copyright (c) 2003,2004 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "dnsproxy.h" struct internal { unsigned int addr; unsigned int mask; struct internal *next; }; static struct internal *internals = NULL; int add_internal(char *s) { char *p; int mask; struct in_addr addr; struct internal *ipa; if (s == NULL) return 0; if ((p = strchr(s, '/')) != NULL) { mask = strtol(p+1, NULL, 10) % 32; *p = '\0'; } else { mask = 32; } if (inet_pton(AF_INET, s, &addr) != 1) return 0; if ((ipa = calloc(1, sizeof(struct internal))) == NULL) fatal("calloc: %s", strerror(errno)); memcpy(&ipa->addr, &addr, 4); ipa->mask = htonl(0xffffffff << (32 - mask)); ipa->addr &= ipa->mask; ipa->next = internals; internals = ipa; DPRINTF(("add_internal %s/%d (%08x/%08x)\n", inet_ntoa(addr), mask, ipa->addr, ipa->mask)); return 1; } int is_internal(struct in_addr arg) { unsigned int addr; struct internal *p; DPRINTF(("is_internal(%s)\n", inet_ntoa(arg))); memcpy(&addr, &arg, 4); for (p = internals; p != NULL; p = p->next) { DPRINTF(("%08x == %08x & %08x ?\n", p->addr, addr, p->mask)); if (p->addr == (addr & p->mask)) return 1; } return 0; } dnsproxy-master/dnsproxy.h0000644000000000000000000000637614151175173015013 0ustar rootroot/* * Copyright (c) 2003,2004,2005,2010 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef _DNSPROXY_H_ #define _DNSPROXY_H_ /* LONGLONG */ #include #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #if HAVE_ARPA_INET_H # include #endif #include #include #ifdef DEBUG #define DPRINTF(x) do { printf x ; } while (0) #else #define DPRINTF(x) #endif #ifdef GLOBALS #define GLOBAL(a) a #define GLOBAL_INIT(a,b) a = b #else #define GLOBAL(a) extern a #define GLOBAL_INIT(a,b) extern a #endif struct request { unsigned short id; struct sockaddr_in client; unsigned short clientid; unsigned char recursion; struct event timeout; struct request **prev; struct request *next; }; GLOBAL_INIT(unsigned int authoritative_port, 53); GLOBAL_INIT(unsigned int authoritative_timeout, 10); GLOBAL_INIT(unsigned int recursive_port, 53); GLOBAL_INIT(unsigned int recursive_timeout, 90); GLOBAL_INIT(unsigned int stats_timeout, 3600); GLOBAL_INIT(unsigned int port, 53); GLOBAL(char *authoritative); GLOBAL(char *chrootdir); GLOBAL(char *listenat); GLOBAL(char *recursive); GLOBAL(char *user); GLOBAL(unsigned long active_queries); GLOBAL(unsigned long all_queries); GLOBAL(unsigned long authoritative_queries); GLOBAL(unsigned long recursive_queries); GLOBAL(unsigned long removed_queries); GLOBAL(unsigned long dropped_queries); GLOBAL(unsigned long answered_queries); GLOBAL(unsigned long dropped_answers); GLOBAL(unsigned long late_answers); GLOBAL(unsigned long hash_collisions); /* dnsproxy.c */ void signal_handler(int, short, void *); /* daemon.c */ int daemon(int, int); /* hash.c */ void hash_add_request(struct request *); void hash_remove_request(struct request *); struct request *hash_find_request(unsigned short); /* internal.c */ int add_internal(char *); int is_internal(struct in_addr); /* log.c */ void log_syslog(const char *); void info(const char *, ...); void error(const char *, ...); void fatal(const char *, ...); /* parse.c */ int parse(const char *); /* statistics.c */ void statistics_start(void); #endif /* _DNSPROXY_H_ */ dnsproxy-master/log.c0000644000000000000000000000364614151175173013676 0ustar rootroot/* * Copyright (c) 2003,2004,2005 Armin Wolfermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "dnsproxy.h" static int log_on_syslog = 0; void log_syslog(const char *tag) { openlog(tag, LOG_NDELAY, LOG_DAEMON); ++log_on_syslog; } static void log_printf(int level, const char *fmt, va_list ap) { if (log_on_syslog) vsyslog(level, fmt, ap); else { (void)vfprintf(stderr, fmt, ap); if (strchr(fmt, '\n') == NULL) fprintf(stderr, "\n"); } } void info(const char *fmt, ...) { va_list ap; va_start(ap, fmt); log_printf(LOG_INFO, fmt, ap); va_end(ap); } void error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); log_printf(LOG_ERR, fmt, ap); va_end(ap); } void fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); log_printf(LOG_ERR, fmt, ap); va_end(ap); exit(1); } dnsproxy-master/Makefile.am0000644000000000000000000000050414151175173014773 0ustar rootrootsbin_PROGRAMS = dnsproxy dnsproxy_SOURCES = dnsproxy.c dnsproxy.h \ daemon.c hash.c internal.c log.c parse.c stats.c man_MANS = dnsproxy.8 distclean-local: rm -rf autom4te.cache dnsproxy-[0-9]* rm -f aclocal.m4 compile config.* configure depcomp install-sh \ INSTALL Makefile.in missing