forked from hswaw/hscloud
198 lines
4.1 KiB
Go
198 lines
4.1 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"crypto/x509"
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
|
||
|
pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
|
||
|
"github.com/golang/glog"
|
||
|
"google.golang.org/grpc"
|
||
|
"google.golang.org/grpc/credentials"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
flagVerifier string
|
||
|
flagIdentity string
|
||
|
flagRouterID string
|
||
|
flagV6 bool
|
||
|
flagLocalIP string
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
flag.Set("logtostderr", "true")
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
flag.StringVar(&flagVerifier, "verifier", "", "Verifier endpoint")
|
||
|
flag.StringVar(&flagIdentity, "identity", "", "Router identity")
|
||
|
flag.StringVar(&flagRouterID, "router_id", "", "Router ID")
|
||
|
flag.StringVar(&flagLocalIP, "local_ip", "", "Local IP")
|
||
|
flag.BoolVar(&flagV6, "v6", false, "V6")
|
||
|
|
||
|
flag.Parse()
|
||
|
|
||
|
if flagVerifier == "" {
|
||
|
glog.Exit("verifier must be set")
|
||
|
}
|
||
|
if flagIdentity == "" {
|
||
|
glog.Exit("identity must be set")
|
||
|
}
|
||
|
if flagRouterID == "" {
|
||
|
glog.Exit("router_id must be set")
|
||
|
}
|
||
|
|
||
|
cpool, _ := x509.SystemCertPool()
|
||
|
creds := credentials.NewClientTLSFromCert(cpool, "")
|
||
|
conn, err := grpc.Dial(flagVerifier, grpc.WithTransportCredentials(creds))
|
||
|
if err != nil {
|
||
|
glog.Exitf("Dial: %v", err)
|
||
|
}
|
||
|
|
||
|
ctx := context.Background()
|
||
|
verifier := pb.NewVerifierClient(conn)
|
||
|
|
||
|
req := &pb.RouterHeartbeatRequest{
|
||
|
Name: flagIdentity,
|
||
|
}
|
||
|
|
||
|
res, err := verifier.RouterHeartbeat(ctx, req)
|
||
|
if err != nil {
|
||
|
glog.Exitf("RouterHeartbeat: %v", err)
|
||
|
}
|
||
|
|
||
|
var config string
|
||
|
if flagV6 {
|
||
|
config = `
|
||
|
log syslog all;
|
||
|
|
||
|
router id %s;
|
||
|
debug protocols { states, interfaces, events };
|
||
|
|
||
|
timeformat base iso long;
|
||
|
timeformat log iso long;
|
||
|
timeformat protocol iso long;
|
||
|
timeformat route iso long;
|
||
|
|
||
|
protocol device {}
|
||
|
|
||
|
function net_martians() {
|
||
|
return net ~ [ fc00::/7+, fec0::/10+, ::/128-, ::/0{0,15}, ::/0{49,128} ];
|
||
|
}
|
||
|
|
||
|
function generic_in() {
|
||
|
if net_martians() then return false;
|
||
|
if bgp_path.len > 64 then return false;
|
||
|
if net.len > 64 then return false;
|
||
|
if net.len < 12 then return false;
|
||
|
return true;
|
||
|
}
|
||
|
`
|
||
|
config = fmt.Sprintf(config, flagRouterID)
|
||
|
} else {
|
||
|
config = `
|
||
|
log syslog all;
|
||
|
|
||
|
router id %s;
|
||
|
debug protocols { states, interfaces, events };
|
||
|
|
||
|
timeformat base iso long;
|
||
|
timeformat log iso long;
|
||
|
timeformat protocol iso long;
|
||
|
timeformat route iso long;
|
||
|
|
||
|
protocol device {}
|
||
|
|
||
|
function net_martians() {
|
||
|
return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
|
||
|
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} ];
|
||
|
}
|
||
|
|
||
|
function generic_in() {
|
||
|
if net_martians() then return false;
|
||
|
if bgp_path.len > 64 then return false;
|
||
|
if net.len > 24 then return false;
|
||
|
if net.len < 8 then return false;
|
||
|
return true;
|
||
|
}
|
||
|
`
|
||
|
config = fmt.Sprintf(config, flagRouterID)
|
||
|
}
|
||
|
|
||
|
sort.Slice(res.AsConfigs, func(i, j int) bool {
|
||
|
return res.AsConfigs[i].Asn < res.AsConfigs[j].Asn
|
||
|
})
|
||
|
|
||
|
for _, asc := range res.AsConfigs {
|
||
|
sort.Slice(asc.Routers, func(i, j int) bool {
|
||
|
return asc.Routers[i].Password < asc.Routers[j].Password
|
||
|
})
|
||
|
for i, router := range asc.Routers {
|
||
|
addr := ""
|
||
|
if flagV6 {
|
||
|
addr = router.Ipv6
|
||
|
} else {
|
||
|
addr = router.Ipv4
|
||
|
}
|
||
|
if addr == "" {
|
||
|
continue
|
||
|
}
|
||
|
peerid := fmt.Sprintf("PEER_%d_%d", asc.Asn, i)
|
||
|
prefixes := []string{}
|
||
|
for _, prefix := range asc.Prefixes {
|
||
|
if flagV6 && !strings.Contains(prefix.Prefix, ":") {
|
||
|
continue
|
||
|
}
|
||
|
if !flagV6 && !strings.Contains(prefix.Prefix, ".") {
|
||
|
continue
|
||
|
}
|
||
|
parts := strings.Split(prefix.Prefix, "/")
|
||
|
addr := parts[0]
|
||
|
bits := parts[1]
|
||
|
filter := fmt.Sprintf("%s/%s{%s,%d}", addr, bits, bits, prefix.MaxLength)
|
||
|
if fmt.Sprintf("%d", prefix.MaxLength) == bits {
|
||
|
filter = fmt.Sprintf("%s/%s", addr, bits)
|
||
|
}
|
||
|
prefixes = append(prefixes, filter)
|
||
|
}
|
||
|
if len(prefixes) == 0 {
|
||
|
continue
|
||
|
}
|
||
|
allowed := strings.Join(prefixes, ",")
|
||
|
|
||
|
part := `
|
||
|
filter %s_in {
|
||
|
if !generic_in() then reject;
|
||
|
if net ~ [ %s ] then accept;
|
||
|
reject;
|
||
|
}
|
||
|
`
|
||
|
part = fmt.Sprintf(part, peerid, allowed)
|
||
|
config += part
|
||
|
|
||
|
part = `
|
||
|
filter %s_out {
|
||
|
accept;
|
||
|
}
|
||
|
`
|
||
|
part = fmt.Sprintf(part, peerid)
|
||
|
config += part
|
||
|
|
||
|
part = `
|
||
|
protocol bgp %s {
|
||
|
local %s as 208521;
|
||
|
neighbor %s as %d;
|
||
|
import filter %s_in;
|
||
|
}
|
||
|
`
|
||
|
part = fmt.Sprintf(part, peerid, flagLocalIP, addr, asc.Asn, peerid)
|
||
|
config += part
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fmt.Println(config)
|
||
|
}
|