惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
GbyAI
GbyAI
WordPress大学
WordPress大学
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
量子位
S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
S
Security Affairs
Cisco Talos Blog
Cisco Talos Blog
Jina AI
Jina AI
L
LINUX DO - 热门话题
Microsoft Security Blog
Microsoft Security Blog
aimingoo的专栏
aimingoo的专栏
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
H
Hacker News: Front Page
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
The Last Watchdog
The Last Watchdog
P
Proofpoint News Feed
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
IT之家
IT之家
A
About on SuperTechFans
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
The Register - Security
The Register - Security
T
Threatpost
Last Week in AI
Last Week in AI
The Hacker News
The Hacker News
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Security @ Cisco Blogs
Project Zero
Project Zero
N
News | PayPal Newsroom
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
K
Kaspersky official blog
雷峰网
雷峰网
W
WeLiveSecurity
博客园 - 聂微东
D
DataBreaches.Net
博客园 - 司徒正美
V2EX - 技术
V2EX - 技术

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
BGP Edge Hygiene at a PCI-Regulated Fintech: IRR + RPKI in Production
Berik Ashimo · 2026-05-16 · via DEV Community

A single hijacked prefix can route a chunk of payment traffic into a stranger's network for half an hour before anyone notices. For a payment provider, that is not a routing incident. It is a regulatory event, an exposed-traffic incident, and an auditor knocking on Monday morning.

This post walks through the BGP edge hygiene we ran in production at a national fintech: what we filtered, how we automated it, what broke, and a copy-paste checklist at the end.

The threat model in 200 words

If you run a public-facing AS, the internet routing system trusts you and your peers to announce only what you should announce. That trust is not enforced by default. Five classes of problem will hurt you:

  1. Route hijacks where a remote AS originates your prefix and pulls traffic away.
  2. Route leaks where a transit customer accidentally re-announces full tables to a peer.
  3. Sub-prefix hijacks, more-specific announcements that win longest-prefix-match.
  4. BGP optimizer leaks, a known class of incident where a vendor box generates synthetic more-specifics and a misconfigured peer re-advertises them.
  5. Static fat-fingers from your own ops team.

For a payment provider the consequences are not just availability. They include confidentiality risk on traffic that touches the cardholder data environment, PCI DSS scope expansion, and customer trust damage that lasts longer than any outage.

We treated the BGP edge as a perimeter control, not a routing function. That framing pulled the security team, the compliance team, and the network team into the same review cycle.

Five layers of edge hygiene

We layered five filters on every external eBGP session. Each one alone is insufficient. Together they cut routing-related incidents to near zero over the year we measured.

Layer 1: max-prefix per session

The cheapest, most effective control. If a peer accidentally leaks full tables to us, we want to tear the session down, not crash the box.

Cisco IOS-XR:

router bgp 65000
 neighbor 203.0.113.1
  remote-as 64500
  address-family ipv4 unicast
   maximum-prefix 5000 80 restart 5
  !

Enter fullscreen mode Exit fullscreen mode

Junos:

protocols {
    bgp {
        group EBGP-PEERS {
            neighbor 203.0.113.1 {
                family inet {
                    unicast {
                        prefix-limit {
                            maximum 5000;
                            teardown 80 idle-timeout 5;
                        }
                    }
                }
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

The 80% warning threshold is the important part. You want a syslog message before you go down, not after.

Layer 2: AS-path filters

Reject any prefix whose AS-path contains your own ASN. This catches the surprisingly common case where a peer somewhere has a stale route through your AS and tries to send it back to you.

Junos:

policy-options {
    as-path OWN-AS-IN-PATH ".* 65000 .*";
    policy-statement DENY-OWN-AS {
        from as-path OWN-AS-IN-PATH;
        then reject;
    }
}

Enter fullscreen mode Exit fullscreen mode

Also reject paths containing private ASNs (64512 to 65534 and 4200000000 to 4294967294) on peering sessions where they have no business appearing.

Layer 3: IRR-based prefix filters

For every peer that is not a Tier 1 transit, build a per-peer prefix filter from their published as-set in IRR. If a prefix is not in their published origin set, drop it.

Generate with bgpq4:

bgpq4 -h whois.radb.net -4 -A -l PEER-EXAMPLE-IN AS-EXAMPLE

Enter fullscreen mode Exit fullscreen mode

This produces a prefix-list ready to paste into Cisco IOS-XR or Junos config. Pin to a specific IRR source (RADb, RIPE, ARIN) per peer to avoid junk from less-trusted databases.

Layer 4: RPKI Route Origin Validation

RPKI ROV is the only one of these five layers that gives you cryptographic origin authentication. Configure a local validator (Routinator, rpki-client, or OctoRPKI), feed it to the routers, and drop invalid at the edge.

Cisco IOS-XR:

router bgp 65000
 rpki server 192.0.2.10
  transport tcp port 3323
  refresh-time 600
 !
 address-family ipv4 unicast
  bgp bestpath origin-as use validity
 !

route-policy RPKI-DROP-INVALID
  if validation-state is invalid then
    drop
  else
    pass
  endif
end-policy

Enter fullscreen mode Exit fullscreen mode

Apply the policy in on every eBGP session. Do not "prefer valid", drop invalid. Halfway measures here are how partial hijacks slip through.

Run at least two validators. We ran three (Routinator + rpki-client + a vendor appliance) and reconciled them in monitoring. If one validator goes stale, you do not want it silently flipping prefixes to NotFound.

Layer 5: bogons, reserved, and martians

Drop RFC1918, RFC6598 (100.64.0.0/10), documentation prefixes (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24), default route (unless you genuinely accept it), and anything with a prefix length above your accepted maximum (typically /24 for IPv4 and /48 for IPv6).

This catches misconfigurations from your peers more often than malice. It is also what auditors look for in PCI DSS section 1 reviews.

Automating it with Ansible

Manual prefix-list updates do not scale past a handful of peers and they rot fast. IRR data changes daily. We built a small Ansible role that does the boring part.

Pipeline:

  1. Pull each peer's as-set from RADb or RIPE using bgpq4.
  2. Render the per-peer prefix-list with a Jinja2 template.
  3. Diff against the running config. If the delta exceeds a threshold (say, plus or minus 10%), flag for human review instead of pushing.
  4. Push via Netmiko or NAPALM, with commit confirm rollback on Junos and a commit replace with diff preview on IOS-XR.
  5. Re-run nightly via cron. IRR data drifts continuously.

Minimal Ansible task:

- name: Generate prefix-list for peer
  ansible.builtin.command: >
    bgpq4 -h whois.radb.net -4 -A
    -l "{{ peer.name }}-IN"
    {{ peer.as_set }}
  register: prefix_list
  changed_when: false

- name: Render config snippet
  ansible.builtin.template:
    src: peer_filter.j2
    dest: "/var/network-configs/{{ peer.name }}.conf"
  vars:
    prefix_list_body: "{{ prefix_list.stdout }}"

- name: Sanity check delta
  ansible.builtin.script: scripts/diff_check.py "{{ peer.name }}.conf"
  register: delta
  failed_when: delta.rc not in [0, 2]

- name: Apply config
  when: delta.rc == 0
  junipernetworks.junos.junos_config:
    src: "/var/network-configs/{{ peer.name }}.conf"
    comment: "auto-update prefix-list for {{ peer.name }}"
    confirm: 5

Enter fullscreen mode Exit fullscreen mode

The confirm: 5 on Junos is the safety net. If the commit breaks the session and you cannot re-commit within 5 minutes, the box rolls back automatically.

Store every generated config in git. When something goes sideways at 03:00, you want to see what changed in the last 24 hours, not guess.

Three things production taught us

Lesson 1: max-prefix saves you from your peers

A regional peer added a new aggregate to their as-set in IRR. Our nightly job picked it up and added it to the filter. The following morning their upstream withdrew the route entirely. Our session would have accepted the larger filter and idled around the new boundary. The 80% warning threshold on max-prefix fired an alert hours before the session reached the actual limit. We caught the IRR drift before anyone noticed at the routing layer.

The lesson: IRR data is necessary but not authoritative. Always wrap it in a max-prefix that reflects the peer's actual size plus some headroom, not their theoretical max.

Lesson 2: "prefer valid" is not "drop invalid"

Early in the rollout we configured RPKI to prefer valid over invalid rather than dropping invalid outright. The reasoning seemed sound at the time: do not break things on day one.

Then a partial hijack happened. A misconfigured AS announced an invalid origin for a /24 that overlapped a covered /22. "Prefer valid" picked the valid /22, but the more-specific /24 still won longest-prefix match because no valid /24 existed in the BGP table. Traffic for that /24 went to the hijacker for about 12 minutes.

We flipped to drop-invalid on every session that night. We lost a small handful of legitimate prefixes whose ROAs were misconfigured by their owners. We sent them email. They fixed it. Net incident count went down, not up.

Lesson 3: pre-commit diff validation catches typos

An AS-path regex update almost dropped a legitimate transit prefix because the regex matched too aggressively. The Ansible diff-check script flagged a delta of minus 1,200 prefixes against the previous run. We caught it before push.

If your automation does not have a "this change looks too big, ask a human" gate, build one. The cost is one extra step per change. The benefit is not paging your team at 02:00 because a regex ate the internet.

How this maps to PCI DSS

If you operate in a PCI environment, the BGP edge is in scope, even if you sometimes argue otherwise. The relevant controls map cleanly:

  • Requirement 1.2 (network segmentation): A clean edge defines your perimeter. RPKI drop-invalid is the cleanest possible argument that you only accept authenticated origins.
  • Requirement 10 (logging): Every RPKI validation state transition, every max-prefix warning, and every prefix-list change must reach your SIEM. Auditors will ask.
  • Requirement 11.4 (intrusion detection): Anomalous prefix-count deltas, sudden session flaps, and unexpected origin AS changes are network IDS signals. Wire them to alerting.
  • Requirement 6.4 (change management): Git-backed configs, pre-commit diff validation, and commit-confirm rollback are change management. Show the auditor the commit log and the rollback playbook.

Done right, network hygiene becomes compliance-by-design, not a separate workstream.

The take-home checklist

If you are setting this up in your own environment:

[ ] max-prefix per eBGP session, with 80% warning threshold
[ ] AS-path filter rejecting your own ASN in the path
[ ] AS-path filter rejecting private ASNs on public sessions
[ ] IRR prefix filter per non-transit peer, regenerated daily
[ ] RPKI ROV with drop-invalid (not prefer-valid)
[ ] At least two RPKI validators, reconciled in monitoring
[ ] Bogon and reserved prefix drops at the edge
[ ] Maximum prefix length filter (typically /24 v4, /48 v6)
[ ] Pre-commit diff validation with a "too big" abort
[ ] commit-confirm or equivalent rollback on push
[ ] Git-backed configs with audit log
[ ] Logging RPKI state transitions to SIEM
[ ] Alerting on prefix-count delta over 10 percent
[ ] Quarterly review of every peer as-set
[ ] Runbook for sudden BGP session flap

Enter fullscreen mode Exit fullscreen mode

If you implement the first six items, you have removed the largest sources of BGP edge risk for your AS. Everything else is operational polish.

Final note

None of this is novel work. IRR has been around since the 1990s, RPKI since the early 2010s. What is novel is that for most payment providers, fintechs, and regulated networks, this is still not the default configuration. The gap between "everyone should be doing this" and "everyone is doing this" is where edge incidents come from.

If your AS is announced on the public internet and you cannot tick off most of the checklist above, you have homework.


I write about production network reliability, BGP edge security, and infrastructure automation. Find me on LinkedIn or reach out at berik@ashimov.com.