项目作者: s8sg

项目描述 :
An ultra light dns proxy to protect your DNS Server against common DDoS attacks
高级语言: Go
项目地址: git://github.com/s8sg/sipahi.git
创建时间: 2017-12-27T08:30:35Z
项目社区:https://github.com/s8sg/sipahi

开源协议:

下载


SIPAHI is a transparent DNS proxy that works as a traffic rate limiter for DNS servers

NOTE

  • Its Transparent in Layer 7
  • Works with any DNS resolver
  • Meant to protect DNS from DDOS
Getting Started
  1. go get github.com/miekg/dns
  2. go get github.com/pmylund/go-cache
  3. go build sipahi.go

or Just

  1. make build
Useage
  1. $ ./sipahi -h
  2. Usage of ./sipahi:
  3. -6 skip ipv6 record query AAAA
  4. -cache
  5. enable sipahi-cache (default true)
  6. -debug int
  7. debug level 0 1 2
  8. -expire int
  9. default cache expire seconds, -1 means use domain ttl time (default 3600)
  10. -file string
  11. cached file (default "resp_cache.dat")
  12. -dns ,
  13. dns address, use ',' as sep (default "192.168.2.1:53:udp,8.8.8.8:53:udp,8.8.4.4:53:udp,8.8.8.8:53:tcp,8.8.4.4:53:tcp")
  14. -local string
  15. local listen address (default ":53")
  16. -revalidation int
  17. default revalidation period, -1 means never revalidate (default 1800)
  18. -timeout int
  19. read/write timeout (default 200)
  20. -ttl int
  21. default ttl that will be set as validation period (default 1800)

running with default values:

  1. $ sudo ./sipahi
  2. ready for accept connection on tcp/udp :53 ...
  3. ^CSignal received: 2
  4. Shutting Down...
  5. SIPAHI STAT:
  6. COUNTER | VALUE
  7. -------------------------------------------
  8. Total Req | 155522
  9. Cache Hit | 100532
  10. Validation Req | 1400
  11. Validation Err | 0
  12. Dns Query | 3984
  13. Dns Failure | 2570
  14. Resolved | 1418
  15. NXDomain | 66
  16. Refused | 0
  17. Total Failure | 66
How Sipahi Works
Understanding how sipahi verify resolver

Verification of a resolver is required in case the resolver is making request at high rate
Validation loop can be debugged by disabling the rate limit
Validation can also be disabled by providing flag -validate=false

To check sipahi validation loop, lets dig for a domain name google.com

  1. $ dig @127.0.0.1 google.com
  2. ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 google.com
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5234
  7. ;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
  8. ;; WARNING: recursion requested but not available
  9. ;; QUESTION SECTION:
  10. ;google.com. IN A
  11. ;; ANSWER SECTION:
  12. google.com. 1800 IN CNAME 472f0851a62dfc74c5bee85b5c64a546.google.com.
  13. ;; Query time: 10 msec
  14. ;; SERVER: 127.0.0.1#53(127.0.0.1)
  15. ;; WHEN: Fri Sep 15 18:25:59 2017
  16. ;; MSG SIZE rcvd: 95

It will returned a CNAME .google.com
On CNAME response resolver should try to resolve the CNAME like below

  1. $ dig @127.0.0.1 472f0851a62dfc74c5bee85b5c64a546.google.com
  2. ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 472f0851a62dfc74c5bee85b5c64a546.google.com
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26349
  7. ;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
  8. ;; WARNING: recursion requested but not available
  9. ;; QUESTION SECTION:
  10. ;472f0851a62dfc74c5bee85b5c64a546.google.com. IN A
  11. ;; ANSWER SECTION:
  12. 472f0851a62dfc74c5bee85b5c64a546.google.com. 299 IN A 172.217.27.78
  13. ;; Query time: 319 msec
  14. ;; SERVER: 127.0.0.1#53(127.0.0.1)
  15. ;; WHEN: Fri Sep 15 18:26:53 2017
  16. ;; MSG SIZE rcvd: 120

It got the IP from actual resolved address
Once it gets a request for the ealier CNAME, it vaidates the client
A resolver should always make an iterative query for the CNAME response
Now when a request for the same domain from same client is received, the client is already verified for the same

  1. dig @127.0.0.1 google.com
  2. ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 google.com
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19947
  7. ;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
  8. ;; WARNING: recursion requested but not available
  9. ;; QUESTION SECTION:
  10. ;google.com. IN A
  11. ;; ANSWER SECTION:
  12. google.com. 299 IN A 172.217.27.78
  13. ;; Query time: 0 msec
  14. ;; SERVER: 127.0.0.1#53(127.0.0.1)
  15. ;; WHEN: Fri Sep 15 18:27:06 2017
  16. ;; MSG SIZE rcvd: 54

we are verified and you got the response within a sec 0
Once sipahi got the actual DNS response, it caches the DNS response into response cache

The response cache should expire after 5 min

  1. $ dig @127.0.0.1 google.com
  2. ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 google.com
  3. ; (1 server found)
  4. ;; global options: +cmd
  5. ;; Got answer:
  6. ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23320
  7. ;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
  8. ;; WARNING: recursion requested but not available
  9. ;; QUESTION SECTION:
  10. ;google.com. IN A
  11. ;; ANSWER SECTION:
  12. google.com. 299 IN A 172.217.27.78
  13. ;; Query time: 7 msec
  14. ;; SERVER: 127.0.0.1#53(127.0.0.1)
  15. ;; WHEN: Fri Sep 15 18:31:31 2017
  16. ;; MSG SIZE rcvd: 54

it took 7ms now. Cause the resp cache in sipahi is expired after the TTL
period (299ms) but the validation cache is maintained!

After 10min the validation cache would be expired too and a re-validation
would be forced

revalidation flag can be used to change the revalidation period

Test in real scenario

In a real deployment scenario, a host resolve query by application results in a recursive query to the resolver. The resolver then makes an iterative query to the DNS server and send the response to the client. Sipahi is meant to run in between resolver and DNS server which makes it behave just like another dns server.

This can be checked by local resolver by replacing sipahi as a nameserver/DNS.

  • Run sipahi
  • If you are using mac
    1. 1> Goto System Preference -> Network -> Advanced (for the network you using)
    2. 2> Goto DNS tab and set your localhost (127.0.0.1) as only dns
  • If you are using any other linux machine
    1. 1> Open to edit /etc/resolv.conf
    2. 2> Add nameserver as your localhost (127.0.0.1)
    3. nameserver 127.0.0.1