This repository has been archived by the owner on Sep 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
glidden.go
104 lines (97 loc) · 2.32 KB
/
glidden.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"./netfilter"
"code.google.com/p/gopacket/layers"
"encoding/json"
"github.com/armon/consul-api"
"log"
"net"
"time"
)
type Cidr net.IPNet
func (ip *Cidr) UnmarshalJSON(bytes []byte) error {
data := ""
if err := json.Unmarshal(bytes, &data); err != nil {
return err
} else if _, ipnet, err2 := net.ParseCIDR(data); err2 != nil {
return err
} else {
*ip = Cidr(*ipnet)
return nil
}
}
func consulKeys(key string) chan []Cidr {
ch := make(chan []Cidr)
queryopts := consulapi.QueryOptions{WaitTime: 30e9}
go func(key string) {
connecting:
for {
client, err := consulapi.NewClient(consulapi.DefaultConfig())
if err == nil {
kv := client.KV()
looking:
for {
value, queryinfo, err := kv.Get(key, &queryopts)
if err != nil {
log.Println("Error connecting")
time.Sleep(1e9)
continue connecting
}
queryopts.WaitIndex = queryinfo.LastIndex
if value == nil || string(value.Value) == "" {
log.Println("Bad consul value", value)
continue looking
}
cidrs := make([]Cidr, 0, 0)
err = json.Unmarshal(value.Value, &cidrs)
if err != nil {
log.Printf("Consul value %q not json: %q", value, err)
continue looking
}
ch <- cidrs
}
} else {
log.Printf("Could not connect to consul %s", err)
time.Sleep(3000 * time.Millisecond)
}
}
}(key)
return ch
}
func main() {
var err error
allow := consulKeys("allow")
nfq, err := netfilter.NewNFQueue(0, 100, netfilter.NF_DEFAULT_PACKET_SIZE)
if err != nil {
log.Fatalf("Error creating queue", err)
}
defer nfq.Close()
packets := nfq.GetPackets()
cidrs := make([]Cidr, 0, 0)
var address net.IP
loop:
for true {
select {
case cidrs = <-allow:
log.Printf("Recieved %d cidrs", len(cidrs))
case packet := <-packets:
layer := packet.Packet.NetworkLayer()
src, _ := layer.NetworkFlow().Endpoints()
if _, ok := layer.(*layers.IPv4); ok {
address = net.IP(src.Raw()[0:4])
} else {
address = net.IP(src.Raw()[0:16])
}
for _, cidr := range cidrs {
ipnet := net.IPNet(cidr)
if ipnet.Contains(address) {
log.Printf("Allowing because %q contains %q", ipnet, address)
packet.SetVerdict(netfilter.NF_ACCEPT)
continue loop
}
}
log.Printf("Rejecting %q", address)
packet.SetVerdict(netfilter.NF_DROP)
}
}
}