Giter Site home page Giter Site logo

fakedns's Introduction

FakeDns

Update 4/14/2020 - Python 2 support removed and code swapped to Python3

Now with round-robin & improved options!

Bugs: @crypt0s - Twitter

[email protected] - Email

A python regular-expression based DNS server!

USAGE:
./fakedns.py [-h] -c Config path [-i interface IP address] [--rebind]

The dns.conf should be set the following way:

[RECORD TYPE CODE] [python regular expression] [answer] [rebind answer]

The answer could be a ip address or string self, the self syntax sugar will be translated to your current machine's local ip address, such as 192.168.1.100.

If a match is not made, the DNS server will attempt to resolve the request using whatever you have your DNS server set to on your local machine and will proxy the request to that server on behalf of the requesting user.

Supported Request Types

- A
- TXT
- AAAA
- PTR
- SOA

In-Progress Request Types

- MX
- CNAME

Misc

- Supports DNS Rebinding
- Supports round-robin

Round-Robin

Round-robin rules are implemented. Every time a client requests a matching rule, FakeDNS will serve out the next IP in the list of IP's provided in the rule.
A list of IP's is comma-separated.

For example:

A robin.net 1.2.3.4,1.1.1.1,2.2.2.2

Is a round-robin rule for robin.net which will serve out responses pointing to 1.2.3.4, 1.1.1.1, and 2.2.2.2, iterating through that order every time a request is made by any client for the robin.net entry.

NOTE : These IP's aren't included as a list to the client in the response - they still only get just one IP in the response (could change that later)

DNS Rebinding

FakeDNS supports rebinding rules, which basically means that the server accepts a certain number of requests from a client for a domain until a threshold (default 1 request) and then it changes the IP address to a different one.

For example:

A rebind.net 1.1.1.1 10%4.5.6.7

Means that we have an A record for rebind.net which evaluates to 1.1.1.1 for the first 10 tries. On the 11th request from a client which has already made 10 requests, FakeDNS starts serving out the second ip, 4.5.6.7

You can use a list of addresses here and FakeDNS will round-robin them for you, just like in the "regular" rule.

Testing FakeDNS in Docker

(localhost only without extra steps)

I have had a lot of success testing/developing FakeDNS in Docker because it's easier than running it natively on modern Ubuntu installs which have their own DNS services running on port 53 already.

If you want to try it out, you can do so without much heavy lifting by following these steps:

Assuming you are inside the FakeDns directory: sudo docker run --interactive --tty --volume \pwd`:/opt/FakeDns -p 5353:53/udp python:3.8 /opt/FakeDns/fakedns.py -c /opt/FakeDns/dns.conf.example. And to test you can run nslookup -port=5353 testrule.test 127.0.0.1which should return1.1.1.1` on your first request

Or, if you'd like to use docker-compose, simply run docker-compose up and use the same test as above.

fakedns's People

Contributors

allanlewis avatar brannondorsey avatar cambid avatar crypt0s avatar ftanida avatar linuturk avatar mikenawrocki avatar ricterz avatar theaxiom avatar topolik avatar ysmood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fakedns's Issues

Error was handled by sending NONEFOUND

Can we get some more verbosity on this? Thanks.

C:\Tools\FakeDNS>fakedns.py --dns 8.8.8.8 -c C:\Tools\FakeDNS\dns.conf -i 192.168.0.228
>> Parsed 15 rules from C:\Tools\FakeDNS\dns.conf
>> Error was handled by sending NONEFOUND
>> Error was handled by sending NONEFOUND
timed out
timed out
>> Built NONEFOUND response
>> Built NONEFOUND response
>> Error was handled by sending NONEFOUND

Seperate results for seprate clients (feature discussion)

It seems to me, given my limited experience with this tool and combing through the source, that the configuration of both the "round robin" and "dns rebind" behavior is "global". By that I mean that any client will trigger the DNS server to respond with it's next response IP address, rather than having programmed DNS responses maintained separately for separate client. E.g. If my dns.conf looks like this:

A some.website 192.168.200,192.168.1.1

And I make one DNS request from client A, with IP 170.30.28.50, I will receive a response of 192.168.200. If client B, with IP 180.33.250.79 then makes a request it would receive a response of 192.168.1.1.

If, however, I want to do a DNS rebind/round robin attack against multiple client IP addresses at once, it would be useful to "save program state" for each client. For instance, if I delivered a payload that sent one request to my server to GET the payload contents of an HTML file that contained JavaScript that made a second request (using the same domain name, but expecting it to resolve to an IP on the victim's local network), I would want to be able to deliver that payload to two separate clients/victims at the same time without worrying that their activity would interfere with each other. Does that make sense?

Essentially, I'd like the round robin and dns rebind functionality to be local to requesting IPs. If IP A requests once, I'd like it to return 192.168.200, and if IP B requests immediately after, I'd like it to also receive 192.168.200. The next time both of them make a DNS lookup it should resolve to 192.168.1.1 to both of them. Am I correct in assuming this is not how the tool currently works?

The reason I bring this up is that I would be happy to add this functionality, but wanted to first propose it here and discuss it. This is something that would be very useful to me in my research as it allows the tool to be used in a "production" scenario, where many different clients can be attacked at once without stepping on each other's toes so to speak.

Throws exception and exits upon parsing rule starting with wildcard

I'm trying to set up FakeDns to use with LANcache, and whenever I try to add "*.cs.steampowered.com" as a rule, it throws this:

>> Parse rules...
>> cs.steampowered.com -> 192.168.1.33
Traceback (most recent call last):
  File "./fakedns.py", line 103, in <module>
    rules = ruleEngine(path)
  File "./fakedns.py", line 78, in __init__
    self.re_list.append([re.compile(splitrule[0]),splitrule[1]])
  File "/usr/lib/python2.7/re.py", line 190, in compile
    return _compile(pattern, flags)
  File "/usr/lib/python2.7/re.py", line 244, in _compile
    raise error, v # invalid expression
sre_constants.error: nothing to repeat

Prepending with a hash (my horrible attempt at commenting out) seems to make it work fine.

Support time-based rebind attack

Rules should allow user to define expire-time for initial rule upon which FakeDNS begins serving the second set of ip addresses.

return record should encode with latin

shoud encode return record with 'latin', eg:'220'.encode() will get '\xc3\x9c'

class A(DNSResponse):
    def __init__(self, query, record):
        super(A, self).__init__(query)
        self.type = b"\x00\x01"
        self.length = b"\x00\x04"
        self.data = self.get_ip(record).encode('latin')  <----

add an option to return NX DOMAIN for a regex

Great tool!
It would be useful to be able to add an option to return 'no such domain' NX DOMAIN return type for a regex. So that hosts lookup can succeed for some lookups and fail for others.
Thanks

IP response incorrect

In the class A, the method get_ip was returning an incorrect result for the IP "192.168.1.172". The conversion to hex is faulty.

Ignore case in match regex

In using FakeDNS in production, i've found that other DNS servers will often times request records for test.website multiple times like so:

TeST.weBsiTE
tESt.WEbSIte
test.WEBSITE
TEST.website
TeSt.WeBsItE

In transferring my domain's DNS to my custom server running FakeDNS, i saw many such lookups being made, presumably by my domain name provider. All but test.website failed because the re.match() in fakedns.py doesn't ignore case. This RFC states that DNS records should be case insensitive.

NoneFound rule doesn't work on AAAA records

guess this minimal patch would do

diff --git a/fakedns.py b/fakedns.py
index db720ef..e8c5a54 100755
--- a/fakedns.py
+++ b/fakedns.py
@@ -419,6 +419,9 @@ class RuleEngine2:
                 if rule_type.upper() == "AAAA":
                     tmp_ip_array = []
                     for ip in ips:
+                        if ip.lower() == 'none':
+                            tmp_ip_array.append(ip)
+                            continue
                         if _is_shorthand_ip(ip):
                             ip = _explode_shorthand_ip_string(ip)

Automangler

Allow special DNS requests to indicate that FakeDNS should handle them with a rule system embedded within the request itself -- automatically mangling the request based on the request itself.

dns.conf.example uses invalid syntax at L5

Currently

A .*rebind.* 1.1.1.1 2.2.2.2
has a space between 1.1.1.1 and 2.2.2.2. This should be a ,.

While experimenting locally with the python script, I found that issuing a request with nslookup for rebind.com returns 1.1.1.1 as expected. However, future requests of rebind.com return ;; Warning: Message parser reports malformed message packet.

While watching the output of fakedns.py, I found that every request after the first generated this exception:

----------------------------------------
Exception happened during processing of request from ('10.244.0.8', 37657)
Traceback (most recent call last):
  File "/usr/lib/python3.8/socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python3.8/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.8/socketserver.py", line 720, in __init__
    self.handle()
  File "fakedns.py", line 35, in handle
    respond(data, self.client_address, s)
  File "fakedns.py", line 632, in respond
    response = rules.match(p, addr[0])
  File "fakedns.py", line 600, in match
    response = CASE[query.type](query, response_data)
  File "fakedns.py", line 220, in __init__
    self.data = self.get_ip(record)
  File "fakedns.py", line 226, in get_ip
    return b''.join(int(x).to_bytes(1, 'little') for x in ip.split('.'))
  File "fakedns.py", line 226, in <genexpr>
    return b''.join(int(x).to_bytes(1, 'little') for x in ip.split('.'))
ValueError: invalid literal for int() with base 10: ''
----------------------------------------

After inserting a print(ip) immediately above the offending return statement, I found that 1.1.1.1 is printed while processing the first DNS request, but all future ones just print 2. After updating the conf file to use the correct syntax, the issue stopped happening. At first I thought this was a problem in the script, but it appears to be an issue with the example conf.

Crashes when many concurrent requests come in and aren't handled quickly

In certain situations (only tested on windows) the server can become bogged down with requests and not respond to the client before the client closes it's UDP response port. On windows this causes a strange-looking error to bomb out.

Fix may be to streamline the threading in the fakedns service.

FakeDNS :: Docker container for community. [REQUEST]

Is it possible to have a Docker container and a manual for dummies on how to configure the DNS?

If there's enough interest I will make a script for this or a docker image which will be pushed to the docker community hub.

Thank you very much!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.