Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

bgpfix/bgpfix

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

129 Commits
129 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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:

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",
  "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",
  "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",
  "KEEPALIVE",
  null,
  {}
]
[
  "R",
  2,
  "2024-11-28T13:06:49.598",
  "KEEPALIVE",
  null,
  {}
]
[
  "L",
  3,
  "2024-11-28T13:06:54.622",
  "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",
  "UPDATE",
  {
    "attrs": {
      "MP_UNREACH": {
        "flags": "O",
        "value": {
          "af": "IPV4/FLOWSPEC",
          "rules": []
        }
      }
    }
  },
  {}
]
^C

BGP features

RFCs:

Drafts:

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:

Author

Pawel Foremski @pforemski 2023-2026

Releases

Packages

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.