Sign inSign up

paprikkafox/pathforge

By paprikkafox

Updated 7 months ago

Image
0

409

paprikkafox/pathforge repository overview

PathForge

PathForge is a lightweight, modern BGP prefix announcer written in Go.
It periodically fetches lists of IPv4 prefixes (from URLs, local text files, or even domain names via DNS lookup) and announces/withdraws them to your BGP peers — perfect for dynamic blackholing, traffic engineering, or sharing blocklists with upstreams.

Beautifully simple. Ruthlessly effective.

Features

  • Dynamic & static BGP peering

    • Static peers (fixed IP/AS)
    • Dynamic neighbors (accepts connections from any IP in a prefix, ideal for CGNAT/dynamic home routers)
    • Multi-hop / eBGP-multihop support
    • Passive mode for the daemon side
  • Flexible prefix sources

    • Remote URLs (http/https)
    • Local .txt files (single files or entire directories)
    • Domain names inside files → automatic A-record lookup → /32 prefixes
    • Supports plain IPs, CIDRs, comments (#), empty lines
  • Automatic re-announce

    • On new peer established (via monitoring)
    • On scheduled fetch (cron with seconds precision)
  • Smart deduplication
    All prefixes from all sources are merged and deduplicated before announcement

  • Graceful shutdown

    • Handles SIGINT/SIGTERM
    • Withdraws prefixes cleanly on stop
  • Zero external dependencies (except Go stdlib + minimal libs)

  • Docker-ready (multi-stage build, non-root user)

Use Cases

  • Dynamic blackholing / DDoS mitigation
    Automatically announce bogon/spam/malware IPs to your upstreams or scrubbing center

  • Route leaking / advertisement
    Share your own prefixes or customer lists with route collectors, looking glasses, or peers

  • Home / SOHO BGP anycast / filtering
    Run on VPS with static IP, accept BGP from home router behind CGNAT/dynamic IP

  • Security research & threat intel
    Quickly test new blocklists, announce them, and observe propagation

  • Educational / lab setup
    Simple way to play with BGP announcements without heavy routers

Quick Start

# Clone & build
git clone https://github.com/paprikkafox/pathforge.git
cd pathforge
go build -o pathforge ./cmd/server/main.go

# Run with default config
./pathforge

# Or with custom config
./pathforge --config /etc/pathforge/config.yml

Docker one-liner:

docker run -d --name pathforge \
  -v $(pwd)/config.yaml:/etc/pathforge/config.yaml:ro \
  -v $(pwd)/blocklists:/app/blocklists:ro \
  paprikkafox/pathforge:latest

Configuration Example (config.yaml)

# Logging configuration
log:
    level: debug # debug / info / warn / error
    format: console # console or json

# Sources for IP prefixes (URLs + local files with IPs/CIDRs/domains)
fetch:
    urls:
        - https://example.com/blocklist-ipv4.txt
        - https://fake-source.net/list.txt

    local_files:
        - ./my-blocked-hosts.txt # single file with IPs, CIDRs or domains
        - /etc/pathforge/blocklists/ # directory — all .txt files will be read
        - /home/user/custom-prefixes.list # another file example

    interval: "0 */30 * * * *" # cron schedule (with seconds), e.g. every 30 min
    timeout: 30s
    user_agent: "PathForge/1.0 (contact: [email protected])"
    max_retries: 3
    retry_delay: 5s

# BGP settings
bgp:
    local_as: 65001 # Your private ASN on the daemon side
    router_id: "203.0.113.45" # Usually your public/static IP or loopback
    hold_time: 240s
    keepalive: 80s
    next_hop: "203.0.113.45" # IP to put in NEXT-HOP (often public IP or tunnel)

    # Peer groups for dynamic neighbors
    peer_groups:
        - name: "dynamic-home"
          remote_as: 65002 # ASN of your home router / upstream
          description: "Dynamic home router behind NAT/CGNAT"
          multi_hop: true
          multihop_ttl: 64 # Start with 64, increase if needed (64–255)
          passive_mode: true # Daemon waits for incoming connections

    # Dynamic neighbors — accept connections from any IP in prefix
    dynamic_neighbors:
        - prefix: "0.0.0.0/0" # Accept from anywhere (most common & simple)
          peer_group: "dynamic-home"
        # Alternative: narrower range (e.g. typical CGNAT space)
        # - prefix: "100.64.0.0/10"
        #   peer_group: "dynamic-home"

    # Optional: static peers (can be used together with dynamic)
    peers: []
    #  - remote_ip: "198.51.100.10"
    #    remote_as: 64496
    #    description: "Static upstream / route collector"
    #    multi_hop: true
    #    enabled: true

Building & Docker

# Local build
go build -o pathforge ./cmd/server

# Multi-platform Docker build & push
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t paprikkafox/pathforge:latest \
  --push .

Contributing

Pull requests are welcome!
Especially welcome:

  • IPv6 support
  • Better DNS caching/resolution
  • Prometheus metrics
  • More flexible filters on sources

License

MIT


Made with ❤️ and BGP love
PathForge — because announcing routes should be simple and beautiful.

Tag summary

Content type

Image

Digest

sha256:d0990451a

Size

10.5 MB

Last updated

7 months ago

docker pull paprikkafox/pathforge