blob: f4558448c6a05a8361e235a651f048636a2d1d15 [file] [log] [blame]
Serge Bazanskiec71cb52019-08-22 18:13:13 +02001package main
2
3import (
4 "context"
5 "crypto/x509"
6 "flag"
7 "fmt"
8 "sort"
9 "strings"
10
11 pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
12 "github.com/golang/glog"
13 "google.golang.org/grpc"
14 "google.golang.org/grpc/credentials"
15)
16
17var (
18 flagVerifier string
19 flagIdentity string
20 flagRouterID string
21 flagV6 bool
22 flagLocalIP string
23)
24
25func init() {
26 flag.Set("logtostderr", "true")
27}
28
29func main() {
30 flag.StringVar(&flagVerifier, "verifier", "", "Verifier endpoint")
31 flag.StringVar(&flagIdentity, "identity", "", "Router identity")
32 flag.StringVar(&flagRouterID, "router_id", "", "Router ID")
33 flag.StringVar(&flagLocalIP, "local_ip", "", "Local IP")
34 flag.BoolVar(&flagV6, "v6", false, "V6")
35
36 flag.Parse()
37
38 if flagVerifier == "" {
39 glog.Exit("verifier must be set")
40 }
41 if flagIdentity == "" {
42 glog.Exit("identity must be set")
43 }
44 if flagRouterID == "" {
45 glog.Exit("router_id must be set")
46 }
47
48 cpool, _ := x509.SystemCertPool()
49 creds := credentials.NewClientTLSFromCert(cpool, "")
50 conn, err := grpc.Dial(flagVerifier, grpc.WithTransportCredentials(creds))
51 if err != nil {
52 glog.Exitf("Dial: %v", err)
53 }
54
55 ctx := context.Background()
56 verifier := pb.NewVerifierClient(conn)
57
58 req := &pb.RouterHeartbeatRequest{
59 Name: flagIdentity,
60 }
61
62 res, err := verifier.RouterHeartbeat(ctx, req)
63 if err != nil {
64 glog.Exitf("RouterHeartbeat: %v", err)
65 }
66
67 var config string
68 if flagV6 {
69 config = `
70log syslog all;
71
72router id %s;
73debug protocols { states, interfaces, events };
74
75timeformat base iso long;
76timeformat log iso long;
77timeformat protocol iso long;
78timeformat route iso long;
79
80protocol device {}
81
82function net_martians() {
83 return net ~ [ fc00::/7+, fec0::/10+, ::/128-, ::/0{0,15}, ::/0{49,128} ];
84}
85
86function generic_in() {
87 if net_martians() then return false;
88 if bgp_path.len > 64 then return false;
89 if net.len > 64 then return false;
90 if net.len < 12 then return false;
91 return true;
92}
93`
94 config = fmt.Sprintf(config, flagRouterID)
95 } else {
96 config = `
97log syslog all;
98
99router id %s;
100debug protocols { states, interfaces, events };
101
102timeformat base iso long;
103timeformat log iso long;
104timeformat protocol iso long;
105timeformat route iso long;
106
107protocol device {}
108
109function net_martians() {
110 return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
111 127.0.0.0/8+, 224.0.0.0/4+, 240.0.0.0/4+, 0.0.0.0/32-, 0.0.0.0/0{25,32}, 0.0.0.0/0{0,7} ];
112}
113
114function generic_in() {
115 if net_martians() then return false;
116 if bgp_path.len > 64 then return false;
117 if net.len > 24 then return false;
118 if net.len < 8 then return false;
119 return true;
120}
121`
122 config = fmt.Sprintf(config, flagRouterID)
123 }
124
125 sort.Slice(res.AsConfigs, func(i, j int) bool {
126 return res.AsConfigs[i].Asn < res.AsConfigs[j].Asn
127 })
128
129 for _, asc := range res.AsConfigs {
130 sort.Slice(asc.Routers, func(i, j int) bool {
131 return asc.Routers[i].Password < asc.Routers[j].Password
132 })
133 for i, router := range asc.Routers {
134 addr := ""
135 if flagV6 {
136 addr = router.Ipv6
137 } else {
138 addr = router.Ipv4
139 }
140 if addr == "" {
141 continue
142 }
143 peerid := fmt.Sprintf("PEER_%d_%d", asc.Asn, i)
144 prefixes := []string{}
145 for _, prefix := range asc.Prefixes {
146 if flagV6 && !strings.Contains(prefix.Prefix, ":") {
147 continue
148 }
149 if !flagV6 && !strings.Contains(prefix.Prefix, ".") {
150 continue
151 }
152 parts := strings.Split(prefix.Prefix, "/")
153 addr := parts[0]
154 bits := parts[1]
155 filter := fmt.Sprintf("%s/%s{%s,%d}", addr, bits, bits, prefix.MaxLength)
156 if fmt.Sprintf("%d", prefix.MaxLength) == bits {
157 filter = fmt.Sprintf("%s/%s", addr, bits)
158 }
159 prefixes = append(prefixes, filter)
160 }
161 if len(prefixes) == 0 {
162 continue
163 }
164 allowed := strings.Join(prefixes, ",")
165
166 part := `
167filter %s_in {
168 if !generic_in() then reject;
169 if net ~ [ %s ] then accept;
170 reject;
171}
172`
173 part = fmt.Sprintf(part, peerid, allowed)
174 config += part
175
176 part = `
177filter %s_out {
178 accept;
179}
180`
181 part = fmt.Sprintf(part, peerid)
182 config += part
183
184 part = `
185protocol bgp %s {
186 local %s as 208521;
187 neighbor %s as %d;
188 import filter %s_in;
189}
190`
191 part = fmt.Sprintf(part, peerid, flagLocalIP, addr, asc.Asn, peerid)
192 config += part
193 }
194 }
195
196 fmt.Println(config)
197}