MCPcopy Index your code
hub / github.com/bgpfix/bgpfix

github.com/bgpfix/bgpfix @v0.20.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.20.2 ↗ · + Follow
1,258 symbols 5,071 edges 123 files 640 documented · 51%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

# BGPFix Golang Library

Go Reference

A generic-purpose, high-performance Golang library for bridging the gaps in BGP.

For a stand-alone tool, see bgpipe: BGP pipeline processor.

Summary

BGPFix can "fix" or "extend" BGP sessions in-flight, possibly adding new features or security layers to proprietary BGP speakers (think big router vendors). The project vision is to allow implementing: * bidirectional BGP session to JSON translation, replacing exabgp for some use-cases, * transparent BGP proxy, optionally rewriting and filtering messages in-flight, * streaming MRT files to BGP routers, adding the necessary OPEN negotiation beforehand, * Flowspec data plane firewalls using Linux Netfilter, * passive inspection (and storage) of ongoing BGP sessions, like in tcpdump, * cool new BGP extensions for legacy speakers, eg. RPKI and ASPA validation, Only To Customer (OTC) attribute, or even BGPSec, * protecting from grave flaws in BGP error handling, and possibly other flaws found using BGP fuzzing projects * academic research ideas, eg. Pretty Good BGP or protection against distributed prefix de-aggregation attacks.

Idea

The overall idea is presented below. You don't need to use the whole library, eg. you may stick to the basic BGP message marshal / unmarshal procedures.

bgpfix idea

The above explains the concept of a Pipe: it has two directions used to exchange BGP messages between 2 speakers on the left (L) and right (R) hand side of the picture.

Each Msg sent to the In channel of a particular direction will go through a set of callbacks (think "plugins") configured in the pipe Options. Each callback can read, write, modify, synthesize, or drop messages before they reach the Out channel. In addition to BGP messages, callbacks may emit Events - such as the standard events of the Pipe - which event handlers may subscribe to in the pipe Options.

Example

A basic example on how to establish a BGP session with a router, and print all messages as JSON to stdout:

package main

import (
    "context"
    "flag"
    "fmt"
    "io"
    "net"
    "net/netip"
    "os"

    "github.com/bgpfix/bgpfix/dir"
    "github.com/bgpfix/bgpfix/msg"
    "github.com/bgpfix/bgpfix/pipe"
    "github.com/bgpfix/bgpfix/speaker"
)

var (
    opt_active = flag.Bool("active", false, "send OPEN first")
    opt_asn    = flag.Int("asn", 65055, "local ASN number")
    opt_hold   = flag.Int("hold", 60, "local hold timer")
    opt_id     = flag.String("id", "1.1.1.1", "local Id (must be IPv4 address)")
)

func main() {
    // parse flags
    flag.Parse()
    if flag.NArg() == 0 {
        fmt.Printf("usage: bgpfix [OPTIONS] <target:port>\n")
        os.Exit(1)
    }

    // create a Pipe, add callback and event handlers
    p := pipe.NewPipe(context.Background())
    p.OnMsg(print, dir.DIR_LR) // call print() on every message in any direction
    p.OnEvent(event)           // call event() on any pipe event

    // L side: a TCP target, sending to R
    conn, err := net.Dial("tcp", flag.Arg(0)) // assumes a ":179" suffix
    if err != nil {
        panic(err)
    }

    // R side: a local speaker, sending to L
    spk := speaker.NewSpeaker(context.Background())
    spk.Options.Passive = !*opt_active
    spk.Options.LocalASN = *opt_asn
    spk.Options.LocalHoldTime = *opt_hold
    spk.Options.LocalId = netip.MustParseAddr(*opt_id)
    spk.Attach(p, dir.DIR_L)

    // copy from conn -> R
    go func() {
        io.Copy(p.R, conn)
        p.Stop()
    }()

    // copy from L -> conn
    go func() {
        io.Copy(conn, p.L)
        p.Stop()
    }()

    // start and wait till all processing is done
    p.Start()
    p.Wait()
}

func print(m *msg.Msg) bool {
    os.Stdout.Write(m.GetJSON())
    return true
}

func event(ev *pipe.Event) bool {
    switch ev.Type {
    case pipe.EVENT_ESTABLISHED:
        fmt.Printf("session established, capabilities: %s\n", ev.Pipe.Caps.String())
    }
    return true
}

JSON

BGPFix has full, bi-directional BGP to JSON translation support.

For example, below we use bgpipe to connect to the Flowspec version of the great BGP Blackholing project by @LukaszBromirski.

$ bgpipe --log disabled --stdout \
    -- speaker --active --asn 65055 \
    -- connect 85.232.240.180 | jq .
[
  "R",
  1,
  "2024-11-28T13:06:47.574",
  -1,
  "OPEN",
  {
    "bgp": 4,
    "asn": 65055,
    "id": "0.0.0.1",
    "hold": 90,
    "caps": {
      "MP": [
        "IPV4/UNICAST",
        "IPV4/FLOWSPEC",
        "IPV6/UNICAST",
        "IPV6/FLOWSPEC"
      ],
      "ROUTE_REFRESH": true,
      "EXTENDED_MESSAGE": true,
      "AS4": 65055
    }
  },
  {}
]
[
  "L",
  1,
  "2024-11-28T13:06:49.598",
  56,
  "OPEN",
  {
    "bgp": 4,
    "asn": 65055,
    "id": "85.232.240.180",
    "hold": 7200,
    "caps": {
      "MP": [
        "IPV4/FLOWSPEC"
      ],
      "ROUTE_REFRESH": true,
      "EXTENDED_NEXTHOP": [
        "IPV4/UNICAST/IPV6",
        "IPV4/MULTICAST/IPV6",
        "IPV4/MPLS_VPN/IPV6"
      ],
      "AS4": 65055,
      "PRE_ROUTE_REFRESH": true
    }
  },
  {}
]
[
  "L",
  2,
  "2024-11-28T13:06:49.598",
  0,
  "KEEPALIVE",
  null,
  {}
]
[
  "R",
  2,
  "2024-11-28T13:06:49.598",
  0,
  "KEEPALIVE",
  null,
  {}
]
[
  "L",
  3,
  "2024-11-28T13:06:54.622",
  316,
  "UPDATE",
  {
    "attrs": {
      "ORIGIN": {
        "flags": "T",
        "value": "IGP"
      },
      "ASPATH": {
        "flags": "T",
        "value": []
      },
      "LOCALPREF": {
        "flags": "T",
        "value": 100
      },
      "ORIGINATOR": {
        "flags": "O",
        "value": "85.232.240.170"
      },
      "CLUSTER_LIST": {
        "flags": "O",
        "value": [
          "85.232.240.180"
        ]
      },
      "MP_REACH": {
        "flags": "OX",
        "value": {
          "af": "IPV4/FLOWSPEC",
          "nexthop": "192.0.2.1",
          "rules": [
            {
              "SRC": "2.59.255.53/32",
              "PROTO": [
                {
                  "op": "==",
                  "val": 6
                }
              ],
              "PORT_DST": [
                {
                  "op": "==",
                  "val": 25
                }
              ]
            },
            {
              "SRC": "5.29.8.251/32",
              "PROTO": [
                {
                  "op": "==",
                  "val": 6
                }
              ],
              "PORT_DST": [
                {
                  "op": "==",
                  "val": 25
                }
              ]
            },
// *** ... cut many, many lines ... ***
            {
              "SRC": "220.158.197.0/24",
              "PROTO": [
                {
                  "op": "==",
                  "val": 6
                }
              ],
              "PORT_DST": [
                {
                  "op": "==",
                  "val": 25
                }
              ]
            }
          ]
        }
      },
      "EXT_COMMUNITY": {
        "flags": "OT",
        "value": [
          {
            "type": "FLOW_RATE_BYTES",
            "value": 0
          }
        ]
      }
    }
  },
  {}
]
[
  "L",
  9,
  "2024-11-28T13:06:54.708",
  10,
  "UPDATE",
  {
    "attrs": {
      "MP_UNREACH": {
        "flags": "O",
        "value": {
          "af": "IPV4/FLOWSPEC",
          "rules": []
        }
      }
    }
  },
  {}
]
^C

BGP features

RFCs: * RFC1997 BGP Communities Attribute * RFC2918 Route Refresh Capability for BGP-4 * RFC4360 BGP Extended Communities Attribute * RFC4271 A Border Gateway Protocol 4 (BGP-4) * RFC4456 BGP Route Reflection: An Alternative to Full Mesh Internal BGP (IBGP) * RFC4760 Multiprotocol Extensions for BGP-4 * RFC5492 Capabilities Advertisement with BGP-4 * RFC5668 4-Octet AS Specific BGP Extended Community * RFC6793 BGP Support for Four-Octet Autonomous System (AS) Number Space * RFC6396 Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format * RFC7854 BGP Monitoring Protocol (BMP) * RFC7911 Advertisement of Multiple Paths in BGP * RFC8092 BGP Large Communities Attribute * RFC8654 Extended Message Support for BGP * RFC8950 Advertising IPv4 Network Layer Reachability Information (NLRI) with an IPv6 Next Hop * RFC8955 Dissemination of Flow Specification Rules * RFC8956 Dissemination of Flow Specification Rules for IPv6 * RFC9072 Extended Optional Parameters Length for BGP OPEN Message * RFC9234 Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages

Drafts: * draft-simpson-idr-flowspec-redirect: BGP Flow-Spec Extended Community for Traffic Redirect to IP Next Hop * draft-walton-bgp-hostname-capability-02: Hostname Capability for BGP

Note: some of the above correspond to partial or work-in-progress support.

Alternatives

If you're interested in bgpfix, you might also want to see: * exabgp * corebgp * xBGP * RouteNormalizer * BGPKIT

Author

Pawel Foremski @pforemski 2023-2026

Extension points exported contracts — how you extend this code

Cap (Interface)
go:generate go run github.com/dmarkham/enumer -type=Code -trimprefix CAP_ Cap represents a particular BGP capability [7 …
caps/cap.go
FlowValue (Interface)
FlowValue represents a Flowspec component value [31 implementers]
attrs/mp-flowspec.go
ExtcomValue (Interface)
Extended Community Value [31 implementers]
attrs/ext-com.go
Value (Interface)
Value represents an optional, arbitrary value attached to a message [37 implementers]
msg/msg.go
CallbackFunc (FuncType)
CallbackFunc processes message m. Return false to drop the message.
pipe/options.go
MPValue (Interface)
MP attribute Value
attrs/mp.go
Attr (Interface)
Attr represents a particular BGP path attribute
attrs/attr.go
NewFunc (FuncType)
NewFunc returns a new instance of capability cc.
caps/cap.go

Core symbols most depended-on inside this repo

NewAttr
called by 70
attrs/attr.go
Run
called by 67
rtr/rtr.go
Unmarshal
called by 55
attrs/attr.go
NewMsg
called by 50
msg/msg.go
NewClient
called by 48
rtr/rtr.go
NewBmp
called by 48
bmp/bmp.go
resBool
called by 39
filter/filter.go
NewOpenBmp
called by 39
bmp/openbmp.go

Shape

Method 583
Function 572
Struct 71
TypeAlias 19
FuncType 7
Interface 6

Languages

Go100%

Modules by API surface

bmp/wire_test.go82 symbols
rtr/rtr_test.go81 symbols
attrs/mp-flowspec.go45 symbols
attrs/common.go44 symbols
filter/filter_test.go37 symbols
attrs/wire_test.go37 symbols
msg/update.go29 symbols
json/json.go26 symbols
msg/wire_test.go25 symbols
attrs/ext-com.go25 symbols
pipe/pipe_test.go24 symbols
attrs/ext-com-flowspec.go24 symbols

For agents

$ claude mcp add bgpfix \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact