mirror of
https://github.com/miekg/dns.git
synced 2025-12-16 17:21:17 +01:00
Add funkenstorm
Added funkenstorm, only does stripping of additional section Fix encoding of ipv4 addresses that are put in a 16 byte buffer (AAAA). Just assume the last four bytes are ipv4 in that case
This commit is contained in:
parent
131b3f388b
commit
05c75c348b
2
README
2
README
@ -12,7 +12,7 @@ be build with: make examples (after the dns package has been installed)
|
|||||||
|
|
||||||
The major omission at the moment is parsing Resource Records from
|
The major omission at the moment is parsing Resource Records from
|
||||||
strings. (I.e. supporting the 1035 zone file format).
|
strings. (I.e. supporting the 1035 zone file format).
|
||||||
Everything else should be present and working. If not, drop me an mail.
|
Everything else should be present and working. If not, drop me an email.
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
Miek Gieben - 2010, 2011 - miek@miek.nl
|
Miek Gieben - 2010, 2011 - miek@miek.nl
|
||||||
|
|||||||
1
TODO
1
TODO
@ -1,5 +1,6 @@
|
|||||||
Todo:
|
Todo:
|
||||||
* NSEC and nsec3 closest encloser helper functions
|
* NSEC and nsec3 closest encloser helper functions
|
||||||
|
* os.Error in Pack()/Unpack()
|
||||||
* wildcards
|
* wildcards
|
||||||
* Tsig testing
|
* Tsig testing
|
||||||
* Private key file parsing use io.Reader (or the like)
|
* Private key file parsing use io.Reader (or the like)
|
||||||
|
|||||||
@ -1,19 +1,15 @@
|
|||||||
|
EXAMPLES=mx \
|
||||||
|
q \
|
||||||
|
chaos \
|
||||||
|
axfr \
|
||||||
|
notify \
|
||||||
|
reflect \
|
||||||
|
rude \
|
||||||
|
s \
|
||||||
|
funkensturm \
|
||||||
|
|
||||||
all:
|
all:
|
||||||
gomake -C mx # query for MX records
|
for i in $(EXAMPLES); do gomake -C $$i; done
|
||||||
gomake -C q # Dig-like tool
|
|
||||||
gomake -C chaos # show version.bind and hostname.bind
|
|
||||||
gomake -C axfr # perform an AXFR
|
|
||||||
gomake -C notify # send a notify msg
|
|
||||||
gomake -C reflect # a reflector nameserver
|
|
||||||
gomake -C rude # a rude nameserver (send formerr back)
|
|
||||||
goamke -C s # a complete nameserver
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
gomake -C mx clean
|
for i in $(EXAMPLES); do gomake -C $$i clean; done
|
||||||
gomake -C q clean
|
|
||||||
gomake -C chaos clean
|
|
||||||
gomake -C axfr clean
|
|
||||||
gomake -C notify clean
|
|
||||||
gomake -C reflect clean
|
|
||||||
gomake -C rude clean
|
|
||||||
goamke -C s
|
|
||||||
|
|||||||
8
_examples/funkensturm/Makefile
Normal file
8
_examples/funkensturm/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
TARG=funkensturm
|
||||||
|
GOFILES=funkensturm.go
|
||||||
|
DEPS=../../
|
||||||
|
include $(GOROOT)/src/Make.cmd
|
||||||
19
_examples/funkensturm/doc.go
Normal file
19
_examples/funkensturm/doc.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Funkensturm rewrites DNS packets in the broadest sense of the word.
|
||||||
|
The features include delayed (re)sending of packets, (re)sending
|
||||||
|
packets to multiple servers, rewriting the packet contents, for instance
|
||||||
|
by signing a packet, or the other way around, stripping the signatures.
|
||||||
|
|
||||||
|
In its essence this is no different that a recursive nameserver, which also
|
||||||
|
receives and sends queries. The difference is the huge amount of tweaking
|
||||||
|
funkensturm offers.
|
||||||
|
|
||||||
|
It includes a configuration language which makes setting up funkensturm
|
||||||
|
real easy. (It may be the case that this configuration language will be Go)
|
||||||
|
|
||||||
|
Not sure if this is doable:
|
||||||
|
- support packet of death (TSIG signed) for stopping funkensturm
|
||||||
|
- support packet of config (TSIG signed) for configuring funkensturm on the fly
|
||||||
|
|
||||||
|
*/
|
||||||
|
package documentation
|
||||||
118
_examples/funkensturm/funkensturm.go
Normal file
118
_examples/funkensturm/funkensturm.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Funkensturm
|
||||||
|
* Miek Gieben <miek@miek.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
_ "fmt"
|
||||||
|
"dns"
|
||||||
|
"strconv"
|
||||||
|
"dns/resolver"
|
||||||
|
"dns/responder"
|
||||||
|
"runtime"
|
||||||
|
"os/signal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type server responder.Server
|
||||||
|
|
||||||
|
func reply(a net.Addr, in []byte, tcp bool) *dns.Msg {
|
||||||
|
inmsg := new(dns.Msg)
|
||||||
|
if !inmsg.Unpack(in) {
|
||||||
|
println("Unpacking failed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's valid mesg, return it
|
||||||
|
return inmsg
|
||||||
|
|
||||||
|
if inmsg.MsgHdr.Response == true {
|
||||||
|
return nil // Don't answer responses
|
||||||
|
}
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.MsgHdr.Id = inmsg.MsgHdr.Id
|
||||||
|
m.MsgHdr.Authoritative = true
|
||||||
|
m.MsgHdr.Response = true
|
||||||
|
m.MsgHdr.Opcode = dns.OpcodeQuery
|
||||||
|
|
||||||
|
m.MsgHdr.Rcode = dns.RcodeSuccess
|
||||||
|
m.Question = make([]dns.Question, 1)
|
||||||
|
m.Answer = make([]dns.RR, 1)
|
||||||
|
m.Extra = make([]dns.RR, 1)
|
||||||
|
|
||||||
|
r := new(dns.RR_A)
|
||||||
|
r.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
|
||||||
|
ip, _ := net.ResolveUDPAddr(a.String()) // No general variant for both upd and tcp
|
||||||
|
r.A = ip.IP.To4() // To4 very important
|
||||||
|
|
||||||
|
t := new(dns.RR_TXT)
|
||||||
|
t.Hdr = dns.RR_Header{Name: "whoami.miek.nl.", Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
|
||||||
|
if tcp {
|
||||||
|
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
|
||||||
|
} else {
|
||||||
|
t.Txt = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Question[0] = inmsg.Question[0]
|
||||||
|
m.Answer[0] = r
|
||||||
|
m.Extra[0] = t
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
||||||
|
m := reply(a, i, false)
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// okay, send it using the resolver
|
||||||
|
qr <- resolver.Msg{m, nil, nil}
|
||||||
|
in := <-qr
|
||||||
|
|
||||||
|
// Okay, not strip the additional section
|
||||||
|
if len(in.Dns.Extra) > 0 {
|
||||||
|
println("Stripping additional section")
|
||||||
|
in.Dns.Extra = []dns.RR{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in may be nil
|
||||||
|
out, ok := in.Dns.Pack()
|
||||||
|
if !ok {
|
||||||
|
println("Failed to pack")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
responder.SendUDP(out, c, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) ResponderTCP(c *net.TCPConn, in []byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
var qr chan resolver.Msg
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
runtime.GOMAXPROCS(5)
|
||||||
|
|
||||||
|
r := new(resolver.Resolver)
|
||||||
|
r.Servers = []string{"127.0.0.1"}
|
||||||
|
r.Port = "53"
|
||||||
|
qr = r.NewQuerier()
|
||||||
|
|
||||||
|
s := new(responder.Server)
|
||||||
|
s.Address = "127.0.0.1"
|
||||||
|
s.Port = "8053"
|
||||||
|
var srv *server
|
||||||
|
ch := make(chan bool)
|
||||||
|
go s.NewResponder(srv, ch)
|
||||||
|
|
||||||
|
forever:
|
||||||
|
for {
|
||||||
|
// Wait for a signal to stop
|
||||||
|
select {
|
||||||
|
case <-signal.Incoming:
|
||||||
|
println("Signal received, stopping")
|
||||||
|
break forever
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
msg.go
27
msg.go
@ -274,17 +274,27 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
|
|||||||
off += len(data)
|
off += len(data)
|
||||||
}
|
}
|
||||||
case "A":
|
case "A":
|
||||||
// It must be a slice of 4
|
// It must be a slice of 4, even if it is 16, we encode
|
||||||
if fv.Len() > net.IPv4len || off+fv.Len() > len(msg) {
|
// only the first 4
|
||||||
|
if off+net.IPv4len > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow packing A")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
|
if fv.Len() == net.IPv6len {
|
||||||
|
msg[off] = byte(fv.Elem(12).(*reflect.UintValue).Get())
|
||||||
|
msg[off+1] = byte(fv.Elem(13).(*reflect.UintValue).Get())
|
||||||
|
msg[off+2] = byte(fv.Elem(14).(*reflect.UintValue).Get())
|
||||||
|
msg[off+3] = byte(fv.Elem(15).(*reflect.UintValue).Get())
|
||||||
|
} else {
|
||||||
msg[off] = byte(fv.Elem(0).(*reflect.UintValue).Get())
|
msg[off] = byte(fv.Elem(0).(*reflect.UintValue).Get())
|
||||||
msg[off+1] = byte(fv.Elem(1).(*reflect.UintValue).Get())
|
msg[off+1] = byte(fv.Elem(1).(*reflect.UintValue).Get())
|
||||||
msg[off+2] = byte(fv.Elem(2).(*reflect.UintValue).Get())
|
msg[off+2] = byte(fv.Elem(2).(*reflect.UintValue).Get())
|
||||||
msg[off+3] = byte(fv.Elem(3).(*reflect.UintValue).Get())
|
msg[off+3] = byte(fv.Elem(3).(*reflect.UintValue).Get())
|
||||||
|
}
|
||||||
off += net.IPv4len
|
off += net.IPv4len
|
||||||
case "AAAA":
|
case "AAAA":
|
||||||
if fv.Len() > net.IPv6len || off+fv.Len() > len(msg) {
|
if fv.Len() > net.IPv6len || off+fv.Len() > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow packing AAAA")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
for j := 0; j < net.IPv6len; j++ {
|
for j := 0; j < net.IPv6len; j++ {
|
||||||
@ -400,7 +410,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
switch fv := val.Field(i).(type) {
|
switch fv := val.Field(i).(type) {
|
||||||
default:
|
default:
|
||||||
BadType:
|
BadType:
|
||||||
fmt.Fprintf(os.Stderr, "dns: unknown packing type %v", f.Type)
|
fmt.Fprintf(os.Stderr, "dns: unknown unpacking type %v", f.Type)
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
case *reflect.SliceValue:
|
case *reflect.SliceValue:
|
||||||
switch f.Tag {
|
switch f.Tag {
|
||||||
@ -409,6 +419,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
return len(msg), false
|
return len(msg), false
|
||||||
case "A":
|
case "A":
|
||||||
if off+net.IPv4len > len(msg) {
|
if off+net.IPv4len > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking A")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
b := net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])
|
b := net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])
|
||||||
@ -416,6 +427,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
off += net.IPv4len
|
off += net.IPv4len
|
||||||
case "AAAA":
|
case "AAAA":
|
||||||
if off+net.IPv6len > len(msg) {
|
if off+net.IPv6len > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking AAAA")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
p := make(net.IP, net.IPv6len)
|
p := make(net.IP, net.IPv6len)
|
||||||
@ -425,6 +437,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
off += net.IPv6len
|
off += net.IPv6len
|
||||||
case "OPT": // EDNS
|
case "OPT": // EDNS
|
||||||
if off+2 > len(msg) {
|
if off+2 > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking OPT")
|
||||||
// No room for anything else
|
// No room for anything else
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -432,6 +445,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
opt[0].Code, off = unpackUint16(msg, off)
|
opt[0].Code, off = unpackUint16(msg, off)
|
||||||
optlen, off1 := unpackUint16(msg, off)
|
optlen, off1 := unpackUint16(msg, off)
|
||||||
if off1+int(optlen) > len(msg) {
|
if off1+int(optlen) > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking OPT")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
opt[0].Data = hex.EncodeToString(msg[off1 : off1+int(optlen)])
|
opt[0].Data = hex.EncodeToString(msg[off1 : off1+int(optlen)])
|
||||||
@ -448,6 +462,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
window := int(msg[off])
|
window := int(msg[off])
|
||||||
blocks := int(msg[off+1])
|
blocks := int(msg[off+1])
|
||||||
if off+blocks > len(msg) {
|
if off+blocks > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking NSEC")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
off += 2
|
off += 2
|
||||||
@ -499,6 +514,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
goto BadType
|
goto BadType
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
if off+1 > len(msg) {
|
if off+1 > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking uint8")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
i := uint8(msg[off])
|
i := uint8(msg[off])
|
||||||
@ -507,12 +523,14 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
var i uint16
|
var i uint16
|
||||||
if off+2 > len(msg) {
|
if off+2 > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking uint16")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
i, off = unpackUint16(msg, off)
|
i, off = unpackUint16(msg, off)
|
||||||
fv.Set(uint64(i))
|
fv.Set(uint64(i))
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
if off+4 > len(msg) {
|
if off+4 > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking uint32")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
|
i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
|
||||||
@ -522,6 +540,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
// This is *only* used in TSIG where the last 48 bits are occupied
|
// This is *only* used in TSIG where the last 48 bits are occupied
|
||||||
// So for now, assume a uint48 (6 bytes)
|
// So for now, assume a uint48 (6 bytes)
|
||||||
if off+6 > len(msg) {
|
if off+6 > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: overflow unpacking uint64")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
i := uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
|
i := uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
|
||||||
@ -573,10 +592,12 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
|
|||||||
case "domain-name":
|
case "domain-name":
|
||||||
s, off, ok = unpackDomainName(msg, off)
|
s, off, ok = unpackDomainName(msg, off)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: failure unpacking domain-name")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
case "":
|
case "":
|
||||||
if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
|
if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
|
||||||
|
fmt.Fprintf(os.Stderr, "dns: failure unpacking string")
|
||||||
return len(msg), false
|
return len(msg), false
|
||||||
}
|
}
|
||||||
n := int(msg[off])
|
n := int(msg[off])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user