diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-27 22:56:26 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-27 23:10:55 +0900 |
commit | d6360e2b32932354b300db2c7e7f28b584fb39a2 (patch) | |
tree | e230bd3c4b5f27fa4f572640ead7109eb9109947 | |
parent | 38755839c3e153dbaaec666a74c4392e8ef2c5e3 (diff) |
server: fix RPKI verification to handle ASPATH ATTR TYPE properly
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | server/rpki.go | 27 | ||||
-rw-r--r-- | server/rpki_test.go | 161 | ||||
-rw-r--r-- | server/server.go | 5 | ||||
-rw-r--r-- | table/path.go | 8 |
4 files changed, 183 insertions, 18 deletions
diff --git a/server/rpki.go b/server/rpki.go index 1e743af9..a26f155f 100644 --- a/server/rpki.go +++ b/server/rpki.go @@ -41,6 +41,7 @@ type roa struct { } type roaClient struct { + AS uint32 roas map[bgp.RouteFamily]*radix.Tree outgoing chan []byte config config.RpkiServers @@ -175,7 +176,23 @@ func (c *roaClient) handleGRPC(grpcReq *GrpcRequest) { } } -func validateOne(tree *radix.Tree, cidr string, as uint32) config.RpkiValidationResultType { +func validatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) config.RpkiValidationResultType { + var as uint32 + if asPath == nil || len(asPath.Value) == 0 { + return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND + } + asParam := asPath.Value[len(asPath.Value)-1].(*bgp.As4PathParam) + switch asParam.Type { + case bgp.BGP_ASPATH_ATTR_TYPE_SEQ: + if len(asParam.AS) == 0 { + return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND + } + as = asParam.AS[len(asParam.AS)-1] + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + as = ownAs + default: + return config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND + } _, n, _ := net.ParseCIDR(cidr) ones, _ := n.Mask.Size() prefixLen := uint8(ones) @@ -209,17 +226,21 @@ func validateOne(tree *radix.Tree, cidr string, as uint32) config.RpkiValidation } func (c *roaClient) validate(pathList []*table.Path) { + if c.roas[bgp.RF_IPv4_UC].Len() == 0 && c.roas[bgp.RF_IPv6_UC].Len() == 0 { + return + } for _, path := range pathList { if tree, ok := c.roas[path.GetRouteFamily()]; ok { - path.Validation = validateOne(tree, path.GetNlri().String(), path.GetSourceAs()) + path.Validation = validatePath(c.AS, tree, path.GetNlri().String(), path.GetAsPath()) } } } -func newROAClient(conf config.RpkiServers) (*roaClient, error) { +func newROAClient(as uint32, conf config.RpkiServers) (*roaClient, error) { var url string c := &roaClient{ + AS: as, roas: make(map[bgp.RouteFamily]*radix.Tree), config: conf, } diff --git a/server/rpki_test.go b/server/rpki_test.go index 9dd135ec..590a6a72 100644 --- a/server/rpki_test.go +++ b/server/rpki_test.go @@ -18,33 +18,168 @@ package server import ( "github.com/armon/go-radix" "github.com/osrg/gobgp/config" + "github.com/osrg/gobgp/packet" "github.com/stretchr/testify/assert" "net" + "strconv" + "strings" "testing" ) -func TestValidate(t *testing.T) { +func strToASParam(str string) *bgp.PathAttributeAsPath { + toList := func(asstr, sep string) []uint32 { + as := make([]uint32, 0) + l := strings.Split(asstr, sep) + for _, s := range l { + v, _ := strconv.ParseUint(s, 10, 32) + as = append(as, uint32(v)) + } + return as + } + var atype uint8 + var as []uint32 + if strings.HasPrefix(str, "{") { + atype = bgp.BGP_ASPATH_ATTR_TYPE_SET + as = toList(str[1:len(str)-1], ",") + } else if strings.HasPrefix(str, "(") { + atype = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET + as = toList(str[1:len(str)-1], " ") + } else { + atype = bgp.BGP_ASPATH_ATTR_TYPE_SEQ + as = toList(str, " ") + } + + return bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(atype, as)}) +} + +func validateOne(tree *radix.Tree, cidr, aspathStr string) config.RpkiValidationResultType { + return validatePath(65500, tree, cidr, strToASParam(aspathStr)) +} + +func TestValidate0(t *testing.T) { assert := assert.New(t) tree := radix.New() addROA(tree, 100, net.ParseIP("192.168.0.0"), 24, 32) addROA(tree, 200, net.ParseIP("192.168.0.0"), 24, 24) - r1 := validateOne(tree, "192.168.0.0/24", 100) - assert.Equal(r1, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + var r config.RpkiValidationResultType + + r = validateOne(tree, "192.168.0.0/24", "100") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + + r = validateOne(tree, "192.168.0.0/24", "100 200") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + + r = validateOne(tree, "192.168.0.0/24", "300") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + + r = validateOne(tree, "192.168.0.0/25", "100") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + + r = validateOne(tree, "192.168.0.0/25", "200") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + + r = validateOne(tree, "192.168.0.0/25", "300") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) +} + +func TestValidate2(t *testing.T) { + assert := assert.New(t) + + tree := radix.New() + + var r config.RpkiValidationResultType + + r = validateOne(tree, "10.0.0.0/16", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) + + r = validateOne(tree, "10.0.0.0/16", "65001") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) +} + +func TestValidate3(t *testing.T) { + assert := assert.New(t) + + tree1 := radix.New() + addROA(tree1, 65000, net.ParseIP("10.0.0.0"), 16, 16) + + var r config.RpkiValidationResultType + + r = validateOne(tree1, "10.0.0.0/8", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) + + r = validateOne(tree1, "10.0.0.0/17", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + + tree2 := radix.New() + addROA(tree2, 65000, net.ParseIP("10.0.0.0"), 16, 24) + + r = validateOne(tree2, "10.0.0.0/17", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) +} + +func TestValidate4(t *testing.T) { + assert := assert.New(t) + + tree := radix.New() + addROA(tree, 65000, net.ParseIP("10.0.0.0"), 16, 16) + addROA(tree, 65001, net.ParseIP("10.0.0.0"), 16, 16) + + var r config.RpkiValidationResultType + + r = validateOne(tree, "10.0.0.0/16", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + + r = validateOne(tree, "10.0.0.0/16", "65001") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_VALID) +} + +func TestValidate5(t *testing.T) { + assert := assert.New(t) + + tree := radix.New() + addROA(tree, 65000, net.ParseIP("10.0.0.0"), 17, 17) + addROA(tree, 65000, net.ParseIP("10.0.128.0"), 17, 17) + + var r config.RpkiValidationResultType - r2 := validateOne(tree, "192.168.0.0/24", 200) - assert.Equal(r2, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + r = validateOne(tree, "10.0.0.0/16", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) +} + +func TestValidate6(t *testing.T) { + assert := assert.New(t) + + tree := radix.New() + addROA(tree, 0, net.ParseIP("10.0.0.0"), 8, 32) + + var r config.RpkiValidationResultType + + r = validateOne(tree, "10.0.0.0/7", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) + + r = validateOne(tree, "10.0.0.0/8", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + + r = validateOne(tree, "10.0.0.0/24", "65000") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) +} + +func TestValidate7(t *testing.T) { + assert := assert.New(t) + + tree := radix.New() + addROA(tree, 65000, net.ParseIP("10.0.0.0"), 16, 24) - r3 := validateOne(tree, "192.168.0.0/24", 300) - assert.Equal(r3, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + var r config.RpkiValidationResultType - r4 := validateOne(tree, "192.168.0.0/25", 100) - assert.Equal(r4, config.RPKI_VALIDATION_RESULT_TYPE_VALID) + r = validateOne(tree, "10.0.0.0/24", "{65000}") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) - r5 := validateOne(tree, "192.168.0.0/25", 200) - assert.Equal(r5, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + r = validateOne(tree, "10.0.0.0/24", "{65001}") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) - r6 := validateOne(tree, "192.168.0.0/25", 300) - assert.Equal(r6, config.RPKI_VALIDATION_RESULT_TYPE_INVALID) + r = validateOne(tree, "10.0.0.0/24", "{65000,65001}") + assert.Equal(r, config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND) } diff --git a/server/server.go b/server/server.go index 60aa4d3d..a14f8395 100644 --- a/server/server.go +++ b/server/server.go @@ -112,7 +112,6 @@ func NewBgpServer(port int) *BgpServer { b.policyUpdateCh = make(chan config.RoutingPolicy) b.neighborMap = make(map[string]*Peer) b.listenPort = port - b.roaClient, _ = newROAClient(config.RpkiServers{}) return &b } @@ -144,6 +143,8 @@ func (server *BgpServer) Serve() { g := <-server.globalTypeCh server.bgpConfig.Global = g + server.roaClient, _ = newROAClient(g.GlobalConfig.As, config.RpkiServers{}) + if g.Mrt.FileName != "" { d, err := newDumper(g.Mrt.FileName) if err != nil { @@ -302,7 +303,7 @@ func (server *BgpServer) Serve() { select { case c := <-server.rpkiConfigCh: - server.roaClient, _ = newROAClient(c) + server.roaClient, _ = newROAClient(server.bgpConfig.Global.GlobalConfig.As, c) case c := <-server.bmpConfigCh: server.bmpClient, _ = newBMPClient(c, server.bmpConnCh) case c := <-server.bmpConnCh: diff --git a/table/path.go b/table/path.go index 3cebdb96..5e914975 100644 --- a/table/path.go +++ b/table/path.go @@ -327,6 +327,14 @@ func (path *Path) getPrefix() string { return path.nlri.String() } +func (path *Path) GetAsPath() *bgp.PathAttributeAsPath { + _, attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH) + if attr != nil { + return attr.(*bgp.PathAttributeAsPath) + } + return nil +} + // GetAsPathLen returns the number of AS_PATH func (path *Path) GetAsPathLen() int { |