blob: 457b567a6b112db287411476e07431afce858dce [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
Serge Bazanskief937472019-08-29 14:53:18 +020023 flagUpstream bool
Serge Bazanskiec71cb52019-08-22 18:13:13 +020024)
25
26func init() {
27 flag.Set("logtostderr", "true")
28}
29
30func main() {
31 flag.StringVar(&flagVerifier, "verifier", "", "Verifier endpoint")
32 flag.StringVar(&flagIdentity, "identity", "", "Router identity")
33 flag.StringVar(&flagRouterID, "router_id", "", "Router ID")
34 flag.StringVar(&flagLocalIP, "local_ip", "", "Local IP")
35 flag.BoolVar(&flagV6, "v6", false, "V6")
Serge Bazanskief937472019-08-29 14:53:18 +020036 flag.BoolVar(&flagUpstream, "upstream", false, "Is an upstream router")
Serge Bazanskiec71cb52019-08-22 18:13:13 +020037
38 flag.Parse()
39
40 if flagVerifier == "" {
41 glog.Exit("verifier must be set")
42 }
43 if flagIdentity == "" {
44 glog.Exit("identity must be set")
45 }
46 if flagRouterID == "" {
47 glog.Exit("router_id must be set")
48 }
49
50 cpool, _ := x509.SystemCertPool()
51 creds := credentials.NewClientTLSFromCert(cpool, "")
52 conn, err := grpc.Dial(flagVerifier, grpc.WithTransportCredentials(creds))
53 if err != nil {
54 glog.Exitf("Dial: %v", err)
55 }
56
57 ctx := context.Background()
58 verifier := pb.NewVerifierClient(conn)
59
60 req := &pb.RouterHeartbeatRequest{
61 Name: flagIdentity,
62 }
63
64 res, err := verifier.RouterHeartbeat(ctx, req)
65 if err != nil {
66 glog.Exitf("RouterHeartbeat: %v", err)
67 }
68
69 var config string
70 if flagV6 {
71 config = `
72log syslog all;
73
74router id %s;
75debug protocols { states, interfaces, events };
76
77timeformat base iso long;
78timeformat log iso long;
79timeformat protocol iso long;
80timeformat route iso long;
81
Serge Bazanskief937472019-08-29 14:53:18 +020082define ourASN = %d;
83define filteredNumber = 65666;
84define customerNumber = 65667;
85define martian = 1;
86define prefixTooLong64 = 2;
87define prefixTooLong24 = 3;
88define pathBogon = 4;
89define pathTooLong = 5;
90define pathFirstNotPeer = 6;
91define prefixFiltered = 9;
92
Serge Bazanskiec71cb52019-08-22 18:13:13 +020093protocol device {}
94
95function net_martians() {
96 return net ~ [ fc00::/7+, fec0::/10+, ::/128-, ::/0{0,15}, ::/0{49,128} ];
97}
98
99function generic_in() {
Serge Bazanskief937472019-08-29 14:53:18 +0200100 if net_martians() then {
101 bgp_large_community.add((ourASN, filteredNumber, martian));
102 return false;
103 }
104 if bgp_path.len > 64 then {
105 bgp_large_community.add((ourASN, filteredNumber, pathTooLong));
106 return false;
107 }
108 if net.len > 64 then {
109 bgp_large_community.add((ourASN, filteredNumber, prefixTooLong64));
110 return false;
111 }
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200112 return true;
113}
114`
Serge Bazanskief937472019-08-29 14:53:18 +0200115 config = fmt.Sprintf(config, flagRouterID, 208521)
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200116 } else {
117 config = `
118log syslog all;
119
120router id %s;
121debug protocols { states, interfaces, events };
122
123timeformat base iso long;
124timeformat log iso long;
125timeformat protocol iso long;
126timeformat route iso long;
127
Serge Bazanskief937472019-08-29 14:53:18 +0200128define ourASN = %d;
129define filteredNumber = 65666;
130define customerNumber = 65667;
131define martian = 1;
132define prefixTooLong64 = 2;
133define prefixTooLong24 = 3;
134define pathBogon = 4;
135define pathTooLong = 5;
136define pathFirstNotPeer = 6;
137define prefixFiltered = 9;
138
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200139protocol device {}
140
141function net_martians() {
142 return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
143 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} ];
144}
145
146function generic_in() {
Serge Bazanskief937472019-08-29 14:53:18 +0200147 if net_martians() then {
148 bgp_large_community.add((ourASN, filteredNumber, martian));
149 return false;
150 }
151 if bgp_path.len > 64 then {
152 bgp_large_community.add((ourASN, filteredNumber, pathTooLong));
153 return false;
154 }
155 if net.len > 24 then {
156 bgp_large_community.add((ourASN, filteredNumber, prefixTooLong24));
157 return false;
158 }
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200159 return true;
160}
161`
Serge Bazanskief937472019-08-29 14:53:18 +0200162 config = fmt.Sprintf(config, flagRouterID, 208521)
163 }
164
165 if flagUpstream {
166 config += `
167protocol kernel {
168 scan time 60;
169 import none;
170 export all;
171}
172
173filter UPSTREAM_C3NOC_IN {
174 if net_martians() then reject;
175 if bgp_path.len > 64 then reject;
176 accept;
177}
178
179filter UPSTREAM_C3NOC_OUT {
180 accept;
181}
182
183`
184 if flagV6 {
185 config += `
186protocol bgp UPSTREAM_C3NOC {
187 import filter UPSTREAM_C3NOC_IN;
188 export filter UPSTREAM_C3NOC_OUT;
189 description "UPSTREAM AS13020";
190
191 local 2a0d:eb02:4242:4242::7 as 208521;
192 neighbor 2a0d:eb02:4242:4242::250 as 13020;
193}
194`
195 } else {
196 config += `
197protocol bgp UPSTREAM_C3NOC {
198 import filter UPSTREAM_C3NOC_IN;
199 export filter UPSTREAM_C3NOC_OUT;
200
201 local 185.236.243.7 as 208521;
202 neighbor 185.236.243.250 as 13020;
203}
204`
205 }
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200206 }
207
208 sort.Slice(res.AsConfigs, func(i, j int) bool {
209 return res.AsConfigs[i].Asn < res.AsConfigs[j].Asn
210 })
211
212 for _, asc := range res.AsConfigs {
213 sort.Slice(asc.Routers, func(i, j int) bool {
214 return asc.Routers[i].Password < asc.Routers[j].Password
215 })
216 for i, router := range asc.Routers {
217 addr := ""
218 if flagV6 {
219 addr = router.Ipv6
220 } else {
221 addr = router.Ipv4
222 }
223 if addr == "" {
224 continue
225 }
226 peerid := fmt.Sprintf("PEER_%d_%d", asc.Asn, i)
227 prefixes := []string{}
228 for _, prefix := range asc.Prefixes {
229 if flagV6 && !strings.Contains(prefix.Prefix, ":") {
230 continue
231 }
232 if !flagV6 && !strings.Contains(prefix.Prefix, ".") {
233 continue
234 }
235 parts := strings.Split(prefix.Prefix, "/")
236 addr := parts[0]
237 bits := parts[1]
238 filter := fmt.Sprintf("%s/%s{%s,%d}", addr, bits, bits, prefix.MaxLength)
239 if fmt.Sprintf("%d", prefix.MaxLength) == bits {
240 filter = fmt.Sprintf("%s/%s", addr, bits)
241 }
242 prefixes = append(prefixes, filter)
243 }
244 if len(prefixes) == 0 {
245 continue
246 }
247 allowed := strings.Join(prefixes, ",")
248
249 part := `
250filter %s_in {
251 if !generic_in() then reject;
Serge Bazanskief937472019-08-29 14:53:18 +0200252 if bgp_path.first != %d then {
253 bgp_large_community.add((ourASN, filteredNumber, pathFirstNotPeer));
254 reject;
255 }
256 if bgp_path.last != %d then {
257 bgp_large_community.add((ourASN, filteredNumber, pathFirstNotPeer));
258 reject;
259 }
260 if ! (net ~ [ %s ]) then {
261 bgp_large_community.add((ourASN, filteredNumber, prefixFiltered));
262 reject;
263 }
264 bgp_large_community.add((ourASN, customerNumber, 2137));
265 accept;
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200266}
267`
Serge Bazanskief937472019-08-29 14:53:18 +0200268 part = fmt.Sprintf(part, peerid, asc.Asn, asc.Asn, allowed)
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200269 config += part
270
271 part = `
272filter %s_out {
Serge Bazanskief937472019-08-29 14:53:18 +0200273 if (ourASN, customerNumber, 2137) ~ bgp_large_community then reject;
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200274 accept;
275}
276`
277 part = fmt.Sprintf(part, peerid)
278 config += part
279
280 part = `
281protocol bgp %s {
282 local %s as 208521;
Serge Bazanskief937472019-08-29 14:53:18 +0200283 description "PEER AS%d R%d";
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200284 neighbor %s as %d;
285 import filter %s_in;
Serge Bazanskief937472019-08-29 14:53:18 +0200286 import keep filtered on;
287 export filter %s_out;
Serge Bazanskia2960f52019-08-22 20:13:47 +0200288 password "%s";
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200289}
290`
Serge Bazanskief937472019-08-29 14:53:18 +0200291 part = fmt.Sprintf(part, peerid, flagLocalIP, asc.Asn, i, addr, asc.Asn, peerid, peerid, router.Password)
Serge Bazanskiec71cb52019-08-22 18:13:13 +0200292 config += part
293 }
294 }
295
296 fmt.Println(config)
297}