Fully transparant proxy in a few lines of Go
This commit is contained in:
parent
285c450fa8
commit
035dc7c1d0
1
TODO
1
TODO
|
@ -35,3 +35,4 @@ Funkensturm:
|
|||
actions are defined in calling functions from funkensturm:
|
||||
- sign(RRSET, privKEY), how do you specify WHAT gets signed
|
||||
if rr.Header().Name == "miek.nl." -> sign header -> add sig
|
||||
* use exp/eval - to inteprete the config file??
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package main
|
||||
|
||||
// This is a transparant proxy config. All recevied pkt are just forwarded to the
|
||||
// nameserver, hardcoded to 127.0.0.1 and then return to the original querier
|
||||
|
||||
import (
|
||||
"dns"
|
||||
"dns/resolver"
|
||||
)
|
||||
|
||||
func matchOpcode(m *dns.Msg, d int) (*dns.Msg, bool) {
|
||||
// Matching criteria
|
||||
switch d {
|
||||
case IN:
|
||||
// nothing
|
||||
case OUT:
|
||||
// Note that when sending back only the mangling is important
|
||||
// the actual return code of these function isn't checked by
|
||||
// funkensturm
|
||||
}
|
||||
|
||||
// Packet Mangling functions
|
||||
switch d {
|
||||
case IN:
|
||||
// nothing
|
||||
case OUT:
|
||||
// nothing
|
||||
}
|
||||
return m, true
|
||||
}
|
||||
|
||||
func actionSend(m *dns.Msg, ok bool) (*dns.Msg, bool) {
|
||||
switch ok {
|
||||
case true, false:
|
||||
qr <- resolver.Msg{m, nil, nil}
|
||||
in := <-qr
|
||||
return in.Dns, true
|
||||
}
|
||||
return nil, false // Bug in Go, yes BUG IN GO
|
||||
}
|
||||
|
||||
// qr is global and started by Funkensturm. If you
|
||||
// need 2 or more resolvers, you'll need to start
|
||||
// them yourself. This needs to be a global variable
|
||||
//var qr1 chan resolver.Msg
|
||||
|
||||
// Return the configration
|
||||
func funkensturm() *Funkensturm {
|
||||
f := new(Funkensturm)
|
||||
|
||||
f.Setup = func() bool { return true }
|
||||
|
||||
f.Matches = make([]Match, 1)
|
||||
f.Matches[0].Op = AND
|
||||
f.Matches[0].Func = matchOpcode
|
||||
|
||||
f.Actions = make([]Action, 1)
|
||||
f.Actions[0].Func = actionSend
|
||||
return f
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Funkensturm rewrites DNS packets in the broadest sense of the word.
|
||||
The features include delayed (re)sending of packets, (re)sending
|
||||
The rewritting can 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.
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net"
|
||||
"fmt"
|
||||
"dns"
|
||||
"dns/resolver"
|
||||
"dns/responder"
|
||||
"os/signal"
|
||||
)
|
||||
|
@ -20,8 +21,8 @@ import (
|
|||
// OUT: pkt as received back. Modifications here will reflect
|
||||
// how the packet is send back to the original requester.
|
||||
const (
|
||||
IN = iota
|
||||
OUT
|
||||
IN = iota // set when receiving a packet
|
||||
OUT // set when sending a packet
|
||||
|
||||
OR
|
||||
AND
|
||||
|
@ -40,7 +41,7 @@ type Match struct {
|
|||
// An action is something that is done with a packet. Funkensturm
|
||||
// does not impose any restriction on what this can be.
|
||||
type Action struct {
|
||||
Func func(in *dns.Msg) (*dns.Msg, bool)
|
||||
Func func(*dns.Msg, bool) (*dns.Msg, bool)
|
||||
}
|
||||
|
||||
// A complete config for Funkensturm. All matches in the Matches slice are
|
||||
|
@ -51,12 +52,60 @@ type Action struct {
|
|||
// If the final result is true the action(s) are called. Note that
|
||||
// at least one of these action functions should send the actual message!
|
||||
type Funkensturm struct {
|
||||
Matches []Match
|
||||
Actions []Action
|
||||
Setup func() bool // Inital setup (for extra resolver or ...)
|
||||
Matches []Match // Match- and mangle functions
|
||||
Actions []Action // What to do wit the packets
|
||||
}
|
||||
|
||||
type server responder.Server
|
||||
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
||||
pkt := reply(a, i)
|
||||
if pkt == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Loop through the Match* functions and decide what to do
|
||||
// Note the packet can be changed by these function, this
|
||||
// change is cumulative.
|
||||
ok, ok1 := true, true
|
||||
pkt1 := pkt
|
||||
for _, m := range f.Matches {
|
||||
pkt1, ok1 = m.Func(pkt1, IN)
|
||||
switch m.Op {
|
||||
case AND:
|
||||
ok = ok && ok1
|
||||
case OR:
|
||||
ok = ok || ok1
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the Actions.Func* and do something with the
|
||||
// packet. Note there can only be one return packet. Intermidate
|
||||
// action function should return nil, to signal ... bla bla
|
||||
var resultpkt *dns.Msg
|
||||
for _, a := range f.Actions {
|
||||
resultpkt, ok1 = a.Func(pkt1, ok)
|
||||
}
|
||||
|
||||
// loop again for matching, but now with OUT, this is done
|
||||
// for some last minute packet changing. Note the boolean return
|
||||
// code isn't used any more
|
||||
pkt1 = resultpkt
|
||||
for _, m := range f.Matches {
|
||||
pkt1, _ = m.Func(pkt1, IN)
|
||||
}
|
||||
|
||||
out, ok1 := pkt1.Pack()
|
||||
if !ok1 {
|
||||
println("Failed to pack")
|
||||
return
|
||||
}
|
||||
responder.SendUDP(out, c, a)
|
||||
}
|
||||
|
||||
func (s *server) ResponderTCP(c *net.TCPConn, in []byte) {
|
||||
}
|
||||
|
||||
// Small helper function
|
||||
func reply(a net.Addr, in []byte) *dns.Msg {
|
||||
inmsg := new(dns.Msg)
|
||||
if !inmsg.Unpack(in) {
|
||||
|
@ -69,56 +118,35 @@ func reply(a net.Addr, in []byte) *dns.Msg {
|
|||
return inmsg
|
||||
}
|
||||
|
||||
func (s *server) ResponderUDP(c *net.UDPConn, a net.Addr, i []byte) {
|
||||
pkt := reply(a, i)
|
||||
if pkt == nil {
|
||||
return
|
||||
}
|
||||
// here I need to call funkensturm
|
||||
matches := getMatches()
|
||||
// Setup a responder takes takes care of the incoming queries.
|
||||
type server responder.Server
|
||||
|
||||
ok, ok1 := true, true
|
||||
pkt1 := pkt
|
||||
for _, m := range matches {
|
||||
pkt1, ok1 = m.Func(pkt1, IN)
|
||||
switch m.Op {
|
||||
case AND:
|
||||
ok = ok && ok1
|
||||
case OR:
|
||||
ok = ok || ok1
|
||||
}
|
||||
}
|
||||
// Setup a initial resolver for sending the queries somewhere else.
|
||||
var qr chan resolver.Msg
|
||||
|
||||
if !ok {
|
||||
fmt.Println("We doen niks")
|
||||
return
|
||||
}
|
||||
println("uitkomst: ", ok)
|
||||
fmt.Printf("%v\n", pkt1)
|
||||
|
||||
/*
|
||||
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) {
|
||||
}
|
||||
// The configuration of Funkensturm
|
||||
var f *Funkensturm
|
||||
|
||||
func main() {
|
||||
// Start the stuff the needs started, call init()
|
||||
Funkinit()
|
||||
f = funkensturm()
|
||||
ok := f.Setup()
|
||||
if !ok {
|
||||
fmt.Printf("Setup failed")
|
||||
return
|
||||
}
|
||||
// The resolver
|
||||
r := new(resolver.Resolver)
|
||||
r.Servers = []string{"127.0.0.1"}
|
||||
r.Port = "53"
|
||||
qr = r.NewQuerier() // connect to global qr
|
||||
|
||||
// The responder
|
||||
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)
|
||||
rs := make(chan bool)
|
||||
go s.NewResponder(srv, rs)
|
||||
|
||||
forever:
|
||||
for {
|
||||
|
@ -129,4 +157,8 @@ forever:
|
|||
break forever
|
||||
}
|
||||
}
|
||||
rs <- true // shut down responder
|
||||
qr <- resolver.Msg{} // shut down resolver
|
||||
<-rs
|
||||
<-qr
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue