<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[IPYE]]></title><description><![CDATA[IPYE]]></description><link>https://ipye-com.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 27 Oct 2026 15:21:58 GMT</lastBuildDate><atom:link href="https://ipye-com.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ARP and NDP Spoofing Defenses: DHCP Snooping, DAI, RA Guard, and What Hosts Can Do]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. ARP (IPv4) and…]]></description><link>https://ipye-com.hashnode.dev/arp-and-ndp-spoofing-defenses-dhcp-snooping-dai-ra-guard-and-what-hosts-can-do</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/arp-and-ndp-spoofing-defenses-dhcp-snooping-dai-ra-guard-and-what-hosts-can-do</guid><category><![CDATA[Security]]></category><category><![CDATA[networking]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[layer2]]></category><category><![CDATA[ARP]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 20:46:47 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>ARP (IPv4) and Neighbor Discovery (IPv6) were designed for trusted local networks. Any host on a segment can claim to own an address, or announce itself as the router, and its neighbours believe it. That makes the local link a place where one misbehaving or malicious machine can intercept or disrupt traffic for everyone on the segment. This article describes the attacks, the switch features that prevent them, what you can do on a Linux host or bridge when you lack managed switches, and how to detect trouble. Examples use <code>192.0.2.0/24</code> and <code>2001:db8:100::/64</code>.</p>
<h2>The attacks</h2>
<ul>
<li><strong>ARP spoofing (poisoning).</strong> An attacker sends unsolicited or forged ARP replies, claiming the gateway's IP address with the attacker's MAC address. Victims update their ARP caches and send traffic to the attacker, who can read it, change it, or drop it.</li>
<li><strong>Rogue DHCP server.</strong> An attacker answers DHCP requests with a gateway or DNS server of their choosing.</li>
<li><strong>Rogue router advertisements.</strong> In IPv6, any host can send an RA. Hosts accept it, configure addresses from the advertised prefix, and add the sender as a default router. A rogue RA can redirect or blackhole traffic, and it does not need malice: a laptop with internet-sharing enabled has caused many outages.</li>
<li><strong>NDP spoofing.</strong> Forged neighbour advertisements play the same role as ARP poisoning on IPv6 links. The earlier article on NDP failure modes covers the non-malicious versions of these failures.</li>
</ul>
<p>Note that none of these cross a router. They need access to the same layer 2 segment, so the first defence is small, well-defined segments with controlled access.</p>
<h2>Layered switch defences</h2>
<table>
<thead>
<tr>
<th>Threat</th>
<th>Switch feature</th>
<th>What it does</th>
</tr>
</thead>
<tbody><tr>
<td>Rogue DHCP server</td>
<td>DHCP snooping</td>
<td>Trusts server replies only from designated ports</td>
</tr>
<tr>
<td>ARP spoofing</td>
<td>Dynamic ARP Inspection (DAI)</td>
<td>Drops ARP packets that disagree with trusted bindings</td>
</tr>
<tr>
<td>Source address forgery</td>
<td>IP source guard</td>
<td>Allows traffic only from the address bound to the port</td>
</tr>
<tr>
<td>Rogue RA</td>
<td>RA Guard (RFC 6105)</td>
<td>Drops router advertisements on untrusted ports</td>
</tr>
<tr>
<td>Rogue DHCPv6</td>
<td>DHCPv6-Shield (RFC 7610)</td>
<td>Drops DHCPv6 server messages on untrusted ports</td>
</tr>
<tr>
<td>MAC flooding</td>
<td>Port security</td>
<td>Limits the number of MAC addresses per port</td>
</tr>
</tbody></table>
<p>Names and exact behaviour differ by vendor; the concepts are the same.</p>
<p><strong>DHCP snooping</strong> is the foundation. The switch watches DHCP exchanges and builds a binding table of IP address, MAC address, VLAN, and port. Only ports you designate as trusted (uplinks, the real DHCP server) may send server replies. <strong>DAI</strong> then uses the binding table: an ARP packet whose sender IP and MAC do not match a binding is dropped. Hosts with static addresses need manual bindings or an exception, which is a common source of problems when DAI is first enabled. Roll it out in logging mode first if your switch supports that, and read the logs before enforcing.</p>
<p><strong>RA Guard</strong>, described in RFC 6105, drops RAs arriving on ports where no router is expected. Its limits are known: attackers can try to evade a simple filter by using extension headers or fragmentation, and RFC 7113 discusses these issues. RFC 6980 forbids fragmenting most ND messages, which helps implementers harden against evasion. Treat RA Guard as a strong barrier against accidents and basic attacks, not an absolute defence.</p>
<p><strong>Secure Neighbor Discovery (SEND, RFC 3971)</strong> uses cryptography to authenticate ND messages, but it has seen very little deployment and is not a practical choice for most networks.</p>
<h2>Without managed switches</h2>
<p>If your switches lack these features, move the controls to the router or bridge you do control.</p>
<p>On a Linux bridge, nftables in the bridge family can drop router advertisements coming from user-facing ports:</p>
<pre><code>table bridge filter {
  chain forward {
    type filter hook forward priority 0; policy accept;
    iifname "port-users*" icmpv6 type nd-router-advert drop
  }
}
</code></pre>
<p>Adjust the interface match to your port naming, and test it by sending a deliberate RA from a lab host. Also consider filtering DHCP server messages (UDP source port 67) from untrusted ports in the same way.</p>
<p>On a <strong>host</strong>, particularly a server, reduce its exposure. Servers with static addressing rarely need to accept router advertisements:</p>
<pre><code>sysctl -w net.ipv6.conf.eth0.accept_ra=0
</code></pre>
<p>Set it only where addresses and routes are configured statically, and remember that disabling it also stops SLAAC. A static neighbour entry for the gateway, such as <code>ip neigh replace 192.0.2.1 lladdr &lt;mac&gt; dev eth0 nud permanent</code>, protects a critical server against poisoning of its gateway entry, at the cost of manual maintenance when the gateway's hardware changes.</p>
<h2>Segment design</h2>
<ul>
<li><strong>Use private VLANs or port isolation</strong> where hosts have no business talking to each other, such as customers sharing a switch. If clients cannot send frames to each other, they cannot poison each other.</li>
<li><strong>Put servers on small segments</strong>, ideally routed point-to-point where you control it.</li>
<li><strong>Disable unused ports,</strong> and use 802.1X where practical.</li>
<li><strong>Encrypt the traffic that matters.</strong> TLS, SSH, and VPNs mean a successful man-in-the-middle sees ciphertext. Authentication and encryption are what stop a poisoned neighbour cache from becoming a data breach.</li>
</ul>
<h2>Detection</h2>
<p>Even with controls, watch for trouble. <code>arpwatch</code> records IP and MAC pairs and reports changes. For IPv6, watch for unexpected RAs:</p>
<pre><code>tcpdump -n -i eth0 'icmp6 and icmp6[icmp6type] == icmp6-routeradvert'
</code></pre>
<p>Any RA from a source that is not your router is worth an alert. Some IDS platforms and monitoring scripts do this continuously. Also watch the neighbour tables: <code>ip neigh</code> showing two IP addresses mapped to the same unexpected MAC, or the gateway's MAC changing, deserves an investigation. Remember that legitimate changes occur too, such as failover between redundant gateways, so keep a record of known MAC addresses.</p>
<h2>Responding</h2>
<p>When you find a rogue source, locate its port from the MAC in the switch's address table, disable the port, and clear the poisoned caches on affected hosts. Then check which missing control let it happen.</p>
<p>Layer 2 security is mostly unglamorous configuration: trusted ports, bindings, and filters. Done once and monitored, it removes a class of intermittent failures that are otherwise very hard to diagnose.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[SNMP vs Streaming Telemetry for Small Networks: What to Collect and How]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. Monitoring a network…]]></description><link>https://ipye-com.hashnode.dev/snmp-vs-streaming-telemetry-for-small-networks-what-to-collect-and-how</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/snmp-vs-streaming-telemetry-for-small-networks-what-to-collect-and-how</guid><category><![CDATA[snmp]]></category><category><![CDATA[telemetry]]></category><category><![CDATA[monitoring]]></category><category><![CDATA[#prometheus]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 20:45:31 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>Monitoring a network means getting numbers off devices: interface counters, errors, temperatures, BGP session states. For decades the answer was SNMP, where a collector polls devices on a schedule. Newer devices also offer <strong>streaming telemetry</strong>, where the device pushes data to a collector. Which should a small network use? Usually the answer is "SNMP for what you have, telemetry where the equipment supports it and you have a reason". This article compares them honestly and shows minimal examples. Addresses use <code>192.0.2.1</code> for a router and <code>2001:db8:100::1</code> for its IPv6 address.</p>
<h2>How SNMP works</h2>
<p>An SNMP manager sends requests to an agent on the device. The agent exposes a tree of variables identified by object identifiers (OIDs) and described by MIB files. The commonly used operations are GET for a specific variable, GETNEXT or GETBULK for walking a subtree, and SET (rarely used for monitoring). Devices can also send unsolicited <strong>traps</strong> or <strong>informs</strong> on events. Interface statistics come from the IF-MIB (RFC 2863).</p>
<p>Three practical points:</p>
<ul>
<li><strong>Versions.</strong> SNMPv1 and v2c authenticate with a community string sent in clear text, which is effectively a shared password visible to anyone who can sniff the traffic. SNMPv3 (the architecture is in RFC 3411 onward) adds user-based authentication and optional encryption. Use v3 where you can, and if you must use v2c, restrict it to the management network with an ACL and use a long random string, not <code>public</code>.</li>
<li><strong>64-bit counters.</strong> The older interface counters are 32 bits and wrap quickly on fast links, producing false spikes or dips. The high-capacity counters (<code>ifHCInOctets</code>, <code>ifHCOutOctets</code>) are 64 bits. Always poll those for anything faster than a slow link.</li>
<li><strong>Polling interval.</strong> A collector sees only samples at the polling interval, so short bursts are averaged away. Polling every minute is common; more frequent polling costs the device CPU.</li>
</ul>
<p>A v3 query looks like this, with placeholders for the credentials:</p>
<pre><code>snmpget -v3 -l authPriv -u monuser -a SHA -A "&lt;auth-pass&gt;" \
  -x AES -X "&lt;priv-pass&gt;" 192.0.2.1 IF-MIB::ifHCInOctets.1
</code></pre>
<p>The <code>-l authPriv</code> flag requests both authentication and encryption. Reachability over IPv6 works the same way with a transport prefix such as <code>udp6:[2001:db8:100::1]</code> as the agent address. Keep SNMP's UDP port 161 closed to the internet; an open agent leaks information and can be abused for reflection.</p>
<h2>How streaming telemetry works</h2>
<p>In a telemetry model, the device structures its data according to a YANG model and a collector subscribes to paths in that data. The device streams updates back over a long-lived connection. A widely used interface is <strong>gNMI</strong> (gRPC Network Management Interface), usually paired with the vendor-neutral OpenConfig models, although many devices also stream models defined by the vendor. Subscriptions can be:</p>
<ul>
<li><strong>Sample:</strong> send the value every N seconds.</li>
<li><strong>On change:</strong> send only when the value changes, which suits state such as an interface or BGP session going down.</li>
<li><strong>Once or poll:</strong> request a snapshot.</li>
</ul>
<p>There are other related standards, such as NETCONF (RFC 6241) for configuration and YANG-push (RFC 8641) for subscribed notifications. The BGP Monitoring Protocol (RFC 7854) streams routing information from a router to a collector, which is a different slice of the same idea.</p>
<p>A subscription with the open-source <code>gnmic</code> client looks roughly like this; verify the flags against your version:</p>
<pre><code>gnmic -a 192.0.2.1:57400 -u monuser -p "&lt;password&gt;" --skip-verify \
  subscribe --path "/interfaces/interface/state/counters" \
  --stream-mode sample --sample-interval 10s
</code></pre>
<p>The <code>--skip-verify</code> flag disables certificate checks and belongs only in a lab; use proper TLS verification in production.</p>
<h2>Comparison</h2>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>SNMP polling</th>
<th>Streaming telemetry</th>
</tr>
</thead>
<tbody><tr>
<td>Direction</td>
<td>Collector pulls</td>
<td>Device pushes</td>
</tr>
<tr>
<td>Data model</td>
<td>MIBs and OIDs</td>
<td>YANG models, often OpenConfig</td>
</tr>
<tr>
<td>Typical resolution</td>
<td>Interval of the poll</td>
<td>Can be finer, or on change</td>
</tr>
<tr>
<td>Event detection</td>
<td>Next poll, or a trap</td>
<td>Immediate with on-change</td>
</tr>
<tr>
<td>Device support</td>
<td>Nearly universal</td>
<td>Varies by vendor and software version</td>
</tr>
<tr>
<td>Security</td>
<td>v3 is good; v1/v2c weak</td>
<td>TLS and per-user credentials</td>
</tr>
<tr>
<td>Tooling maturity</td>
<td>Very mature</td>
<td>Growing; more moving parts</td>
</tr>
<tr>
<td>Load on device</td>
<td>Poll cost per request</td>
<td>Subscription held by device</td>
</tr>
</tbody></table>
<h2>What a small network needs</h2>
<p>Most small networks care about a short list:</p>
<ol>
<li>Interface throughput, errors, and discards on uplinks and peering ports.</li>
<li>Device health: CPU, memory, temperature, power.</li>
<li>BGP session state and prefix counts.</li>
<li>Reachability and latency from outside (see the article on active measurement).</li>
<li>Traffic composition, from flow export (NetFlow, sFlow, IPFIX).</li>
</ol>
<p>All of that is available from SNMP on almost any router or switch, and for Linux routers <code>node_exporter</code> and the routing daemon's own interfaces provide the same information. A Prometheus setup with <code>snmp_exporter</code> for network gear and <code>node_exporter</code> for servers covers a lot of ground with little effort. Telemetry earns its place when you need sub-minute resolution, event-driven alerts on state changes, or when a vendor no longer maintains SNMP support for the data you need.</p>
<h2>Practical recommendations</h2>
<ul>
<li><strong>Start with SNMPv3 and 64-bit counters.</strong> It is boring and works.</li>
<li><strong>Monitor state changes with alerts, not graphs.</strong> A graph does not wake anyone; an alert on a BGP session going down does. For devices that support on-change telemetry, this is the strongest argument for it.</li>
<li><strong>Measure the monitoring itself.</strong> Alert if the collector stops receiving data, because a silent failure of monitoring looks like a quiet network.</li>
<li><strong>Protect the credentials.</strong> Keep SNMP credentials and telemetry passwords in a secret store, not in a public repository.</li>
<li><strong>Keep the management plane separate.</strong> Put polling and streaming on a management network or a restricted interface, and apply an ACL on the device.</li>
</ul>
<h2>Migration without drama</h2>
<p>You do not have to choose one. Many networks run SNMP for baseline monitoring indefinitely and add telemetry for a small set of high-value paths, such as uplink counters and BGP state, then compare the two for a while before relying on the new one. If the numbers disagree, find out why before switching dashboards. The right measure of success is not which technology you use, but whether you find out about a problem before your customers do.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[VXLAN and EVPN Basics: An MPLS-Free Way to Stretch Layer 2 Across Routed Networks]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. Sometimes two…]]></description><link>https://ipye-com.hashnode.dev/vxlan-and-evpn-basics-an-mpls-free-way-to-stretch-layer-2-across-routed-networks</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/vxlan-and-evpn-basics-an-mpls-free-way-to-stretch-layer-2-across-routed-networks</guid><category><![CDATA[vxlan]]></category><category><![CDATA[evpn]]></category><category><![CDATA[overlay]]></category><category><![CDATA[bgp]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 19:37:40 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>Sometimes two servers in different racks, or different sites, need to share a layer 2 segment, for example so that virtual machines can keep their addresses when they move. The traditional answer was MPLS-based services, which needs an MPLS-capable core. VXLAN (RFC 7348) offers an alternative that needs only IP connectivity between endpoints, and EVPN (RFC 7432, with RFC 8365 for its use with VXLAN) provides a BGP-based control plane for it. This article explains the data plane, the three ways of learning where MAC addresses live, a small Linux example, and the pitfalls. Examples use <code>192.0.2.0/24</code> for the underlay and <code>2001:db8:100::/48</code> for tenant addressing.</p>
<h2>What VXLAN does</h2>
<p>VXLAN wraps an Ethernet frame in a UDP packet. The outer packet is ordinary IP, so the underlay needs only routing. Key facts:</p>
<ul>
<li>The VXLAN header is 8 bytes and carries a <strong>24-bit VXLAN Network Identifier (VNI)</strong>, which gives roughly 16 million segments, compared with 4094 usable VLAN IDs.</li>
<li>The destination UDP port is 4789 (IANA-assigned). The source port is usually derived from a hash of the inner frame, which gives the underlay's ECMP something to spread on.</li>
<li>The device that adds and removes the header is a <strong>VTEP</strong> (VXLAN Tunnel Endpoint).</li>
<li>The encapsulation adds 50 bytes over an IPv4 underlay (outer Ethernet 14, IP 20, UDP 8, VXLAN 8) and 70 bytes over IPv6. Plan the underlay MTU so that a full-size inner frame still fits, or tenants will see the same fragmentation and black-hole problems described in the earlier MTU articles.</li>
</ul>
<p>VXLAN does not provide encryption or authentication. Anyone who can send UDP packets to a VTEP on port 4789 can inject frames into a segment, so restrict that port to the underlay addresses of your own endpoints and never expose it to the internet.</p>
<h2>How a VTEP finds the other end</h2>
<p>A VTEP needs to know which remote VTEP holds a given MAC address. There are three common approaches:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>How it works</th>
<th>Trade-off</th>
</tr>
</thead>
<tbody><tr>
<td>Static flood list</td>
<td>You list remote VTEP addresses by hand; unknown or broadcast traffic is replicated to each</td>
<td>Simple, fine for two or three sites, does not scale</td>
</tr>
<tr>
<td>Multicast underlay</td>
<td>Each VNI maps to an underlay multicast group</td>
<td>Needs multicast routing in the underlay</td>
</tr>
<tr>
<td>EVPN control plane</td>
<td>BGP distributes MAC and IP reachability between VTEPs</td>
<td>More to configure, scales well, reduces flooding</td>
</tr>
</tbody></table>
<p>Without a control plane, VTEPs learn MAC addresses the way a switch does, from received traffic ("flood and learn"). That works, but flooded traffic is replicated to many places.</p>
<h2>A static Linux example</h2>
<p>Two Linux hosts, <code>192.0.2.1</code> and <code>192.0.2.2</code>, connected by routed IP. On the first:</p>
<pre><code>ip link add vxlan100 type vxlan id 100 local 192.0.2.1 dstport 4789
bridge fdb append 00:00:00:00:00:00 dev vxlan100 dst 192.0.2.2
ip link add br100 type bridge
ip link set vxlan100 master br100
ip link set vxlan100 up
ip link set br100 up
</code></pre>
<p>The all-zero MAC entry in the forwarding database is the flood list: broadcast, multicast, and unknown unicast go to each <code>dst</code> listed, and the device learns remote MACs from received traffic. Mirror it on the second host with the local and destination addresses swapped. Attach VM interfaces or containers to <code>br100</code>, and give tenants addresses such as <code>2001:db8:100:1::/64</code>. Check with <code>bridge fdb show dev vxlan100</code> and <code>ip -d link show vxlan100</code>.</p>
<h2>What EVPN adds</h2>
<p>EVPN uses MP-BGP, with the L2VPN address family (AFI 25) and EVPN subsequent address family (SAFI 70), to carry MAC and IP information. The route types you will meet first:</p>
<ul>
<li><strong>Type 2, MAC/IP advertisement:</strong> announces that a MAC (and optionally an IP) is reachable behind a VTEP.</li>
<li><strong>Type 3, inclusive multicast:</strong> announces a VTEP's interest in a VNI, building the flood list automatically.</li>
<li><strong>Type 5, IP prefix (RFC 9136):</strong> advertises an IP prefix, used for routing between segments.</li>
</ul>
<p>Because MACs and IPs are advertised, VTEPs can answer ARP and Neighbor Discovery locally for known hosts, which reduces flooding. A MAC that moves to another VTEP is re-advertised with a sequence number so others update.</p>
<p>In FRR, with the Linux bridge and VXLAN interface configured as above, the control plane is enabled roughly like this:</p>
<pre><code>router bgp 64496
 neighbor 192.0.2.2 remote-as 64496
 !
 address-family l2vpn evpn
  neighbor 192.0.2.2 activate
  advertise-all-vni
 exit-address-family
</code></pre>
<p><code>advertise-all-vni</code> tells FRR to advertise every locally configured VNI. The VXLAN interface is then typically created with <code>nolearning</code> so that BGP, not data-plane learning, populates the table. Check FRR's EVPN documentation for the exact interface settings of your version, since the recommended Linux setup has evolved.</p>
<h2>Underlay design</h2>
<p>The underlay is plain routing: an IGP or eBGP carries VTEP loopbacks, and ECMP spreads the encapsulated flows across paths. Keep these in mind:</p>
<ol>
<li>VTEP addresses must be reachable from each other, with a stable loopback for each VTEP.</li>
<li>MTU, as above, must be raised end to end.</li>
<li>Filter UDP 4789 at the edge of the underlay.</li>
<li>BFD or fast IGP timers help traffic move off failed links.</li>
</ol>
<h2>When not to use it</h2>
<p>Layer 2 stretching has costs. A broadcast domain that spans sites shares its failures, loops, and noisy neighbours across all of them. If the real need is only IP reachability for a prefix at two sites, plain routing, possibly with a WireGuard tunnel, is usually easier to run. Use VXLAN and EVPN when you genuinely need the same layer 2 segment in multiple places.</p>
<h2>Summary</h2>
<p>VXLAN carries Ethernet frames in UDP across any routed network, identified by a 24-bit VNI. EVPN makes MAC and IP reachability a BGP matter, so you do not rely on flooding alone. Mind the 50-byte overhead, protect port 4789, and think twice before stretching layer 2 where routing would do.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[iBGP vs eBGP: Next-Hop-Self, Loopback Peering, and Why iBGP Needs a Full Mesh]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. When you run a BGP…]]></description><link>https://ipye-com.hashnode.dev/ibgp-vs-ebgp-next-hop-self-loopback-peering-and-why-ibgp-needs-a-full-mesh</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/ibgp-vs-ebgp-next-hop-self-loopback-peering-and-why-ibgp-needs-a-full-mesh</guid><category><![CDATA[ibgp]]></category><category><![CDATA[bgp]]></category><category><![CDATA[routing]]></category><category><![CDATA[networking]]></category><category><![CDATA[ebgp]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 19:32:24 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>When you run a BGP session to a router in a different AS, that is eBGP. When you run one to a router in your own AS, that is iBGP. The protocol is the same, but the defaults and the rules around route propagation differ, and most of the confusing first-time failures in a multi-router network come from those differences. This article walks through them, with a minimal configuration. Examples use AS64496 as your network, AS64497 as an upstream, <code>2001:db8:100::/48</code> as your prefix, and <code>2001:db8:ffff::/64</code> for infrastructure.</p>
<h2>What actually differs</h2>
<table>
<thead>
<tr>
<th>Behaviour</th>
<th>eBGP</th>
<th>iBGP</th>
</tr>
</thead>
<tbody><tr>
<td>Peer AS</td>
<td>Different from yours</td>
<td>Same as yours</td>
</tr>
<tr>
<td>AS_PATH on advertisement</td>
<td>Your ASN is prepended</td>
<td>Left unchanged</td>
</tr>
<tr>
<td>NEXT_HOP on advertisement</td>
<td>Normally set to your own session address</td>
<td>Normally left unchanged</td>
</tr>
<tr>
<td>LOCAL_PREF</td>
<td>Not sent to the peer</td>
<td>Carried between peers</td>
</tr>
<tr>
<td>Loop prevention</td>
<td>Own ASN seen in AS_PATH</td>
<td>Routes learned from an iBGP peer are not passed to other iBGP peers</td>
</tr>
<tr>
<td>Typical TCP TTL</td>
<td>1 on most implementations, so peers must be directly connected unless multihop is configured</td>
<td>Not limited to one hop</td>
</tr>
<tr>
<td>Typical preference (administrative distance)</td>
<td>More preferred</td>
<td>Less preferred</td>
</tr>
</tbody></table>
<p>The last row varies by vendor; in FRR the defaults are 20 for eBGP and 200 for iBGP, which makes the IGP or connected routes win over iBGP-learned ones when both exist.</p>
<h2>The iBGP split-horizon rule</h2>
<p>RFC 4271 says a router must not re-advertise a route learned from one iBGP peer to another iBGP peer. The reason is loop prevention: iBGP does not modify the AS_PATH, so the path attribute cannot catch a loop inside your AS. The consequence is that every iBGP speaker must hear a route directly from the router that learned it from outside, which means a <strong>full mesh</strong> of iBGP sessions. With three routers that is three sessions; the count grows as n(n-1)/2, which is why larger networks use route reflectors or confederations, covered in the next article.</p>
<h2>Why next-hop-self matters</h2>
<p>Suppose your edge router R1 learns <code>2001:db8:200::/48</code> from upstream AS64497 whose session address is <code>2001:db8:fffe::1</code>. R1 passes the route to your internal router R2 over iBGP with the next hop still <code>2001:db8:fffe::1</code>. R2 now needs a route to that address. If the upstream's link subnet is not in your IGP, R2 marks the BGP route as unreachable and will not use it. There are two common fixes:</p>
<ol>
<li>Put the external link subnet into the IGP, usually as a passive interface.</li>
<li>Have R1 set itself as the next hop for iBGP advertisements with <code>next-hop-self</code>, so that R2 only needs to reach R1's loopback.</li>
</ol>
<p>The second option is the one most small operators choose. It keeps external link addressing out of the IGP and means the next hop stays valid as long as R1 is reachable.</p>
<h2>Peer between loopbacks</h2>
<p>An iBGP session between interface addresses dies when that single interface does, even though other paths between the routers exist. Peering between loopback addresses lets the TCP session survive on any working path, provided the IGP carries the loopback routes. You need two things: the session must be sourced from the loopback (<code>update-source</code>), and the IGP, such as OSPF or IS-IS, must advertise both loopbacks. Static routes can serve in a very small network.</p>
<p>A minimal FRR configuration on R1, with R2's loopback as <code>2001:db8:ffff::2</code> and the upstream session on <code>2001:db8:fffe::1</code>:</p>
<pre><code>router bgp 64496
 bgp router-id 192.0.2.1
 neighbor 2001:db8:fffe::1 remote-as 64497
 neighbor 2001:db8:ffff::2 remote-as 64496
 neighbor 2001:db8:ffff::2 update-source lo
 !
 address-family ipv6 unicast
  network 2001:db8:100::/48
  neighbor 2001:db8:fffe::1 activate
  neighbor 2001:db8:fffe::1 route-map UPSTREAM-IN in
  neighbor 2001:db8:fffe::1 route-map UPSTREAM-OUT out
  neighbor 2001:db8:ffff::2 activate
  neighbor 2001:db8:ffff::2 next-hop-self
 exit-address-family
</code></pre>
<p>The route-map names are placeholders for real inbound and outbound policy. Recent FRR versions require such policy on eBGP sessions by default, and RFC 8212 recommends the same behaviour: an eBGP session with no explicit policy should neither accept nor send routes. Write the policy rather than turning that safeguard off.</p>
<p>The reverse configuration on R2 points at R1's loopback, with its own loopback as the update source.</p>
<h2>Things that commonly go wrong</h2>
<ul>
<li><strong>Session stuck in Active or Connect.</strong> The loopback is not reachable through the IGP, or the update source is missing so the TCP session originates from an interface address the peer does not expect.</li>
<li><strong>Route received but not installed.</strong> The next hop is unresolvable. Check <code>show bgp ipv6 unicast &lt;prefix&gt;</code> and look for "inaccessible", then check the route to the next hop.</li>
<li><strong>eBGP to a loopback fails.</strong> With the default TTL of 1, such a session needs multihop. Prefer the link address for eBGP.</li>
<li><strong>Routes visible on R1 only.</strong> The iBGP session exists, but R2 learned the route from R1 and is not allowed to pass it on to R3. This is the split-horizon rule, not a bug.</li>
<li><strong>Exits chosen inconsistently.</strong> LOCAL_PREF is set on one router but not the other, or set after the iBGP advertisement. Set it on import at the edge, so it travels with the route.</li>
</ul>
<h2>Verifying</h2>
<p><code>show bgp summary</code> should show every session established, and external prefixes should have a sensible best path on every internal router. Confirm the next hop with <code>show bgp ipv6 unicast 2001:db8:200::/48</code>, and test forwarding with a traceroute from an internal router rather than assuming that a BGP table entry means a working path.</p>
<h2>Summary</h2>
<p>eBGP crosses AS boundaries and rewrites the path and next hop; iBGP stays inside an AS, preserves attributes, and does not re-advertise to other iBGP peers. Use loopback peering for iBGP, carry the loopbacks in an IGP, set next-hop-self at the edge, and write explicit policy on every eBGP session.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[Sending Email over IPv6: Reverse DNS, SPF, and Deliverability Checks]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. Email is the service…]]></description><link>https://ipye-com.hashnode.dev/sending-email-over-ipv6-reverse-dns-spf-and-deliverability-checks</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/sending-email-over-ipv6-reverse-dns-spf-and-deliverability-checks</guid><category><![CDATA[email]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[spf]]></category><category><![CDATA[RDNS]]></category><category><![CDATA[ #deliverability]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 18:51:15 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>Email is the service where IPv6 most often goes wrong, because receivers apply their strictest checks to the sending address, and IPv6 gives senders more ways to leave an incomplete record trail. A mail server that works perfectly over IPv4 can be rejected or sent to spam over IPv6 for reasons that have nothing to do with the message. This article covers what the receiving side typically verifies, the records you must publish, and how to test. Examples use <code>2001:db8:100::25</code> as the sending IPv6 address, <code>192.0.2.25</code> for IPv4, and <code>mail.example.com</code>.</p>
<h2>What receivers look at</h2>
<p>When your server connects to a receiving server over IPv6, the receiver sees only the connection's source address, the name in your <code>EHLO</code>, and then the message. From those it commonly checks:</p>
<ul>
<li><strong>Reverse DNS.</strong> Does the source address have a PTR record, and does the PTR name resolve back to the same address? This round trip is often called forward-confirmed reverse DNS.</li>
<li><strong>SPF</strong> (RFC 7208). Is the source address authorised by the domain's SPF record?</li>
<li><strong>DKIM and DMARC.</strong> These authenticate the message and the domain, independent of the IP family.</li>
<li><strong>Reputation.</strong> Has this address, or its surrounding network, been seen sending unwanted mail?</li>
</ul>
<p>Large mailbox providers have published sender requirements which include having IPv6 senders publish PTR records and pass authentication; check each provider's current guidelines, because they change. Without a PTR, many receivers will reject or heavily penalise IPv6 mail.</p>
<h2>Reverse DNS for the sending address</h2>
<p>An IPv6 PTR lives under <code>ip6.arpa</code>, with the 32 nibbles of the address written in reverse. For <code>2001:db8:100::25</code>:</p>
<pre><code>5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.8.b.d.0.1.0.0.2.ip6.arpa. IN PTR mail.example.com.
</code></pre>
<p>and the forward record must exist as well:</p>
<pre><code>mail.example.com. IN AAAA 2001:db8:100::25
mail.example.com. IN A    192.0.2.25
</code></pre>
<p>Make sure the name in your <code>EHLO</code> (the hostname Postfix or Exim presents) is the same name, so the greeting, PTR, and forward record all agree. Each sending address needs its own PTR, since a single PTR for one address in a /64 does nothing for the others. If you send from several addresses, set the outbound source address deliberately, because the kernel's default source address selection may choose a different one from the one you published a PTR for. The reverse delegation process is covered in an earlier article.</p>
<h2>SPF with IPv6</h2>
<p>SPF has a separate mechanism for each family: <code>ip4:</code> and <code>ip6:</code>.</p>
<pre><code>example.com. IN TXT "v=spf1 ip4:192.0.2.25 ip6:2001:db8:100::25 -all"
</code></pre>
<p>Points to remember:</p>
<ul>
<li><strong><code>ip6:</code> accepts a prefix</strong>, such as <code>ip6:2001:db8:100::/64</code>. Listing the whole /64 is convenient if you send from several addresses, but it also authorises every address in it, so only do that if you control the whole range.</li>
<li><strong><code>a</code> and <code>mx</code> mechanisms</strong> look up addresses of the named hosts, and match the sender address against both A and AAAA data as appropriate to the connection's family. If your MX host has an AAAA record, it is automatically covered.</li>
<li><strong>The 10-lookup limit</strong> (RFC 7208) applies to mechanisms that cause DNS queries (<code>include</code>, <code>a</code>, <code>mx</code>, <code>exists</code>, <code>redirect</code>), but not to <code>ip4</code> and <code>ip6</code>. Using literal addresses keeps you well below it.</li>
<li>A missing <code>ip6:</code> is the typical reason mail fails SPF on IPv6 only while passing on IPv4.</li>
</ul>
<h2>What to check on the receiving side</h2>
<p>If you accept mail on IPv6 as well, publish an AAAA record for the MX host and make sure the server listens on it. Many sites receive mail only over IPv4 by choice, which is acceptable because senders fall back to IPv4. If you do enable IPv6 inbound, test it, as an MX that answers on IPv6 but is misconfigured loses mail.</p>
<h2>Controlling the family on the sender</h2>
<p>Mail servers decide between IPv4 and IPv6 for outbound connections. In Postfix, <code>inet_protocols</code> (<code>all</code>, <code>ipv4</code>, or <code>ipv6</code>) sets which families the server uses, and <code>smtp_address_preference</code> can bias the choice where supported. Some operators send over IPv4 only while they build reputation for their IPv6 addresses, since a new address has no sending history. That is a reasonable, temporary measure: send a small volume of legitimate mail over IPv6 first, watch the responses, and increase gradually.</p>
<h2>Reputation and the /64</h2>
<p>IPv6 provides so many addresses that blocklists cannot list every individual one. Receivers commonly judge reputation by prefix, often a /64 or something wider. The practical consequences are that a sender sharing a /64 with a spammer can suffer for it, and that moving to a different address in the same /64 does not clear a bad record. If you run mail, ask what shared range you are in, and prefer a block where you control the whole /64.</p>
<h2>A quick test routine</h2>
<pre><code>dig -x 2001:db8:100::25 +short          # PTR
dig AAAA mail.example.com +short        # does it match?
dig TXT example.com +short              # SPF includes ip6:
swaks --to test@example.org --server mx.example.org --from you@example.com
</code></pre>
<p>Send a test message to a mailbox you control at a large provider, and read the full headers. The <code>Authentication-Results</code> header shows the SPF, DKIM, and DMARC outcome and the IP address that was evaluated, so you can see the result as the receiver did, and confirm it was an IPv6 connection (the <code>Received</code> headers show the connecting address).</p>
<h2>Summary checklist</h2>
<table>
<thead>
<tr>
<th>Check</th>
<th>What to confirm</th>
</tr>
</thead>
<tbody><tr>
<td>PTR</td>
<td>Exists for every sending IPv6 address</td>
</tr>
<tr>
<td>Forward</td>
<td>PTR name has matching AAAA record</td>
</tr>
<tr>
<td>EHLO</td>
<td>Same name as the PTR</td>
</tr>
<tr>
<td>SPF</td>
<td><code>ip6:</code> covers the sending address</td>
</tr>
<tr>
<td>DKIM/DMARC</td>
<td>Pass regardless of family</td>
</tr>
<tr>
<td>Reputation</td>
<td>No listing for the address or its /64</td>
</tr>
</tbody></table>
<p>Deliverability over IPv6 is mostly about completeness. Publish the full set of records, keep your sending address predictable, and introduce volume slowly.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[IPv6 in Cloud VMs: What You Actually Get, and Why the /64 Matters]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. When you enable IPv6…]]></description><link>https://ipye-com.hashnode.dev/ipv6-in-cloud-vms-what-you-actually-get-and-why-the-64-matters</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/ipv6-in-cloud-vms-what-you-actually-get-and-why-the-64-matters</guid><category><![CDATA[ipv6]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[vps]]></category><category><![CDATA[SLAAC]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 18:50:03 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>When you enable IPv6 on a cloud or VPS instance, the result varies far more between providers than for IPv4. One gives your VM a single /128 by DHCPv6, another a whole routed /64, a third a block of addresses carved from a shared on-link subnet, and some offer a larger routed prefix. This variation decides what you can build: a single web server is fine with one address, while containers, VMs inside the VM, VPN servers, and mail servers with several identities are not. This article explains the options and why the /64 boundary is special. Examples use <code>2001:db8:100::/48</code>.</p>
<h2>Why /64 is the unit</h2>
<p>IPv6 subnets on ordinary links are /64 for architectural reasons, not wastefulness:</p>
<ul>
<li>The unicast address format in RFC 4291 assumes a 64-bit interface identifier for addresses other than those beginning with binary 000.</li>
<li><strong>SLAAC</strong> (RFC 4862) builds an address from an advertised prefix and an interface identifier, and on Ethernet-like links the identifier is 64 bits long, so the advertised prefix must be a /64.</li>
<li>Neighbour discovery, privacy addresses, and stable-privacy identifiers (RFC 7217, RFC 8981) all assume that the host part is 64 bits.</li>
<li>Operators, and many abuse and reputation systems, treat a /64 as roughly one customer or subscriber (the logging article discusses it).</li>
</ul>
<p>Subnets smaller than /64 are possible with static configuration, but features that depend on the 64-bit boundary stop working, which is a reason to avoid them on links with ordinary hosts.</p>
<h2>The common provisioning models</h2>
<table>
<thead>
<tr>
<th>Model</th>
<th>What the VM gets</th>
<th>What it allows</th>
</tr>
</thead>
<tbody><tr>
<td>Single address (/128)</td>
<td>One address, often DHCPv6</td>
<td>One service per VM</td>
</tr>
<tr>
<td>On-link /64</td>
<td>A /64 shared at layer 2 or per-VM</td>
<td>SLAAC, several addresses on the host</td>
</tr>
<tr>
<td>Routed /64</td>
<td>A /64 routed to the VM's address</td>
<td>Containers, VMs, NDP proxy not needed</td>
</tr>
<tr>
<td>Routed larger prefix</td>
<td>A /56 or /48</td>
<td>Many subnets, tunnels, internal routing</td>
</tr>
</tbody></table>
<p>Read your provider's documentation to see which one you have. The two differ materially in practice: with an <strong>on-link</strong> prefix, the upstream router resolves each address with neighbour discovery, so every additional address you use on the VM must answer Neighbor Solicitations from that router. With a <strong>routed</strong> prefix, the provider forwards the whole range toward your VM's address, and you decide what is inside it.</p>
<h2>Check what you have</h2>
<pre><code>ip -6 addr show scope global
ip -6 route show
ip -6 neigh show
ping -6 -c 3 fe80::1%eth0     # replace with the gateway's link-local address
</code></pre>
<p>If you see a /128 address and a default route via a link-local gateway, you have a single address. A /64 with an <code>on-link</code> route suggests an on-link model. If the provider's panel shows a "routed" prefix, expect a route towards you via your main address and no on-link route for it.</p>
<h2>Using extra addresses on one VM</h2>
<p>Adding addresses from an on-link /64 is simple: <code>ip -6 addr add 2001:db8:100:1::25/64 dev eth0</code>. Because the upstream router resolves by NDP, the kernel answers automatically. Remember to set the preferred outbound source address when it matters, since the default source selection (RFC 6724) may pick a different address from the one you configured for a service, and a mail server's source address has to match its PTR record.</p>
<p>With a routed prefix, add the prefix to an internal bridge or use it for containers, and let the host forward; see the Docker article for the forwarding and RA interplay.</p>
<h2>Security groups and host firewalls</h2>
<p>Cloud firewalls and security groups are separate for IPv4 and IPv6. Opening port 443 to <code>0.0.0.0/0</code> does not open it to <code>::/0</code>, and a rule set copied from the IPv4 side without its IPv6 counterpart is the classic reason that a server answers on one family only. The opposite problem is just as real: if your host firewall is IPv4-only and the VM is globally reachable on IPv6, services you assumed to be private are exposed. Test from outside using <code>nmap -6</code>.</p>
<h2>Reverse DNS and reputation</h2>
<p>With a /128, reverse DNS is whatever the provider offers, often a single PTR in a control panel. With a routed /64 or larger you might be able to delegate <code>ip6.arpa</code> to your own name servers. For mail, you need a PTR for each sending address, and some providers' reputation systems classify at the /64, so a noisy neighbour in an on-link /64 can affect you. If you are in a shared /64, ask whether it is shared at all.</p>
<h2>Avoid these mistakes</h2>
<ul>
<li>Assuming that "IPv6 enabled" means a routed prefix.</li>
<li>Choosing a provider for a service that needs several addresses, such as a VPN or a mail cluster, without checking what it routes.</li>
<li>Leaving router advertisements disabled where the provider relies on them for the default route, or enabling forwarding and losing that route.</li>
<li>Forgetting that DHCPv6 normally conveys no default route, which comes from the RA.</li>
<li>Publishing AAAA records before testing from outside.</li>
</ul>
<p>If your design needs more than one address, a routed /64 at minimum is what you want, and a /56 or /48 if you will have separate subnets. Ask these questions before you commit to a platform, and not when your containers cannot be reached.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[Linux sysctls for IPv6 Servers: The Settings That Matter and the Traps Around Them]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. Linux IPv6 behaviour…]]></description><link>https://ipye-com.hashnode.dev/linux-sysctls-for-ipv6-servers-the-settings-that-matter-and-the-traps-around-them</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/linux-sysctls-for-ipv6-servers-the-settings-that-matter-and-the-traps-around-them</guid><category><![CDATA[Linux]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[sysctl]]></category><category><![CDATA[servers]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 18:48:19 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>Linux IPv6 behaviour is controlled by a small set of sysctls under <code>net.ipv6</code>. Most defaults are sensible for a client or a simple server, but several change meaning as soon as the machine forwards packets, runs containers, or sits behind more than one uplink. This article covers the settings that most often matter on a server, explains the well-known interaction between forwarding and router advertisements, and shows how to apply and verify changes. Examples use <code>2001:db8::/32</code> and the interface name <code>eth0</code>. Always check the kernel documentation (<code>ip-sysctl</code>) for your kernel version.</p>
<h2>Per-interface and global scopes</h2>
<p>Most IPv6 sysctls live in <code>net.ipv6.conf.&lt;interface&gt;.&lt;name&gt;</code>. There are also two special groups: <code>all</code> and <code>default</code>. The <code>default</code> group provides the initial value for interfaces created later; <code>all</code> applies to existing interfaces, though how it combines with the per-interface value depends on the specific setting (for some it is a logical OR or AND, for others a plain override). When in doubt, set the value on <code>all</code>, <code>default</code>, and the specific interface, then read it back.</p>
<h2>The settings worth knowing</h2>
<table>
<thead>
<tr>
<th>Sysctl</th>
<th>Meaning</th>
<th>Server note</th>
</tr>
</thead>
<tbody><tr>
<td><code>forwarding</code></td>
<td>Whether the host routes IPv6 packets</td>
<td>Needed for routers, VPN gateways, container hosts</td>
</tr>
<tr>
<td><code>accept_ra</code></td>
<td>How Router Advertisements are handled</td>
<td>Interacts with <code>forwarding</code> (see below)</td>
</tr>
<tr>
<td><code>autoconf</code></td>
<td>SLAAC address generation from RAs</td>
<td>Disable on interfaces with static addressing</td>
</tr>
<tr>
<td><code>use_tempaddr</code></td>
<td>RFC 8981 temporary addresses</td>
<td>Often 0 on servers, 2 on clients</td>
</tr>
<tr>
<td><code>addr_gen_mode</code></td>
<td>How the interface identifier is generated</td>
<td>Choose stable-privacy or random over EUI-64</td>
</tr>
<tr>
<td><code>accept_redirects</code></td>
<td>Whether ICMPv6 Redirects are honoured</td>
<td>Usually 0 on servers</td>
</tr>
<tr>
<td><code>disable_ipv6</code></td>
<td>Turns IPv6 off for an interface</td>
<td>Prefer firewalling to hiding the stack</td>
</tr>
<tr>
<td><code>dad_transmits</code></td>
<td>Duplicate address detection probes</td>
<td>Rarely changed</td>
</tr>
</tbody></table>
<h2>The forwarding and accept_ra trap</h2>
<p>The most common surprise is this: with <code>accept_ra</code> at its default of 1, the kernel accepts Router Advertisements <strong>only if forwarding is off</strong>. The moment you enable <code>net.ipv6.conf.all.forwarding=1</code>, for example when installing a container runtime or a VPN, the host stops processing RAs. The result is that the default route learned via RA expires and the machine loses IPv6 connectivity a short time later, often minutes after the change.</p>
<p>The values for <code>accept_ra</code> are:</p>
<ul>
<li><code>0</code>: do not accept RAs.</li>
<li><code>1</code>: accept RAs only if forwarding is disabled.</li>
<li><code>2</code>: accept RAs even if forwarding is enabled.</li>
</ul>
<p>If a host both forwards and relies on SLAAC for its upstream route, set <code>accept_ra = 2</code> on the upstream interface:</p>
<pre><code># /etc/sysctl.d/60-ipv6-server.conf
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
</code></pre>
<p>If you use static addressing and a static default route instead, it is cleaner to set <code>accept_ra = 0</code> and <code>autoconf = 0</code> on that interface, so a rogue RA on the segment cannot change your routing.</p>
<h2>Addresses: temporary and stable</h2>
<p>RFC 8981 temporary addresses are valuable on clients, since they change the source address people see. On servers, you normally want a predictable source address for outbound connections, so <code>use_tempaddr = 0</code> is common there. For the permanent address, <code>addr_gen_mode = 2</code> selects stable-privacy generation (RFC 7217), which gives a stable but not hardware-derived identifier; mode 3 generates a random one. Both avoid embedding the MAC address as EUI-64 does. The earlier article on privacy addresses goes into the trade-offs.</p>
<p>If you assign a static address, check with <code>ip -6 addr show dev eth0</code> that the address is not flagged <code>tentative</code> or <code>dadfailed</code>.</p>
<h2>Redirects, source routing, and ICMP rate limiting</h2>
<p>Servers rarely need ICMPv6 Redirects, so <code>accept_redirects = 0</code> removes a way for a neighbour on the same link to influence your routing. Likewise, set <code>accept_source_route = 0</code>, since Routing Header type 0 was deprecated in RFC 5095. The sysctl <code>net.ipv6.icmp.ratelimit</code> bounds how often the kernel sends certain ICMPv6 errors. Do not lower it so far that Path MTU Discovery messages are throttled on a busy router.</p>
<h2>Dual-stack sockets</h2>
<p><code>net.ipv6.bindv6only</code> controls whether a listening socket bound to <code>::</code> also accepts IPv4 connections (as IPv4-mapped addresses). The default of 0 means one socket serves both families. Applications can override it with the <code>IPV6_V6ONLY</code> socket option, and some, such as nginx with <code>ipv6only=on</code>, do so deliberately to bind separate IPv4 and IPv6 sockets.</p>
<h2>Neighbour table limits</h2>
<p>The <code>net.ipv6.neigh.default.gc_thresh1</code>, <code>gc_thresh2</code>, and <code>gc_thresh3</code> values set how large the neighbour cache may grow before garbage collection becomes aggressive and then entries are refused. On a host that serves a whole /64 or fronts many containers, defaults can be too small, and the failure shows up as intermittent unreachability to local addresses with <code>neighbour table overflow</code> in the kernel log. The article on neighbour cache exhaustion covers sizing.</p>
<h2>Applying and verifying</h2>
<pre><code>sysctl -w net.ipv6.conf.eth0.accept_ra=2   # runtime change
sysctl --system                            # reload /etc/sysctl.d/*
sysctl net.ipv6.conf.eth0.accept_ra        # read back
ip -6 route show default                   # is the default route present?
ip -6 addr show dev eth0                   # is the address valid, not tentative?
</code></pre>
<p>Persist settings in a file under <code>/etc/sysctl.d/</code>, and keep that file in configuration management so a rebuilt server behaves the same. Note that settings for interfaces which appear later (a bridge, a VPN device) come from <code>default</code>, so set both <code>all</code> and <code>default</code> in the file. Finally, test from outside after each change, from a host that has native IPv6, and wait longer than the router lifetime in the RA before declaring a forwarding change safe, since the failure mode described above is delayed.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[IPv6 Transition Mechanisms Overview: Dual-Stack, 6rd, DS-Lite, MAP, and 464XLAT]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. "IPv6 transition" is…]]></description><link>https://ipye-com.hashnode.dev/ipv6-transition-mechanisms-overview-dual-stack-6rd-ds-lite-map-and-464xlat</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/ipv6-transition-mechanisms-overview-dual-stack-6rd-ds-lite-map-and-464xlat</guid><category><![CDATA[ipv6]]></category><category><![CDATA[transition]]></category><category><![CDATA[dual-stack]]></category><category><![CDATA[NAT64]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 18:45:38 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>"IPv6 transition" is not one technology. It is a family of mechanisms built for different positions in the network: some for a home user whose ISP has no native IPv6, some for an ISP that wants to run an IPv6-only access network, and some for a mobile carrier whose phones must still run IPv4-only apps. This article lays out the main mechanisms, what each one solves, and which ones a small operator or a server administrator is likely to meet. Examples use <code>2001:db8::/32</code> and <code>192.0.2.0/24</code>.</p>
<h2>Three families of approach</h2>
<p>Almost every transition mechanism falls into one of three groups:</p>
<ol>
<li><strong>Dual-stack:</strong> run both protocols side by side, natively.</li>
<li><strong>Tunnelling:</strong> carry one protocol inside the other across a network that only supports the outer one.</li>
<li><strong>Translation:</strong> convert between IPv4 and IPv6 packets or addresses at a boundary.</li>
</ol>
<p>The mechanisms differ mainly in which protocol the access network carries and where the state lives (on the customer device, or in a central, carrier-operated box).</p>
<h2>Dual-stack</h2>
<p>Dual-stack means every host and router speaks both IPv4 and IPv6, and each service is reachable over both. RFC 4213 describes it together with configured tunnelling. It is the simplest model to reason about because nothing is translated, and IPv6 traffic takes its own native path. Its drawbacks are that you still need IPv4 addresses for every host, and you operate two sets of routing, firewall rules, and monitoring. Clients choose between families using Happy Eyeballs (RFC 8305), covered in an earlier article on dual-stack hygiene.</p>
<h2>Tunnels: 6in4, 6rd, and the obsolete ones</h2>
<p>A <strong>6in4</strong> tunnel (RFC 4213) wraps an IPv6 packet in an IPv4 header, using IP protocol number 41. It is how many people reach IPv6 through a tunnel service when their ISP has none. It needs a public IPv4 address on both ends, and the encapsulation reduces the usable MTU by 20 bytes.</p>
<p><strong>6rd</strong> (RFC 5969) is a variation designed for ISPs. It derives the customer's IPv6 prefix algorithmically from the customer's IPv4 address plus an ISP-owned IPv6 prefix, so a relay inside the ISP network can decapsulate without any per-customer state. The ISP delivers IPv6 over its existing IPv4-only access network, and traffic goes through the ISP's own border relay rather than a third party.</p>
<p>Two older approaches are mostly of historical interest. <strong>6to4</strong> (RFC 3056) used the anycast relay prefix and had well-known reliability problems; RFC 7526 deprecated the anycast prefix. <strong>Teredo</strong> (RFC 4380) tunnelled IPv6 over UDP through NAT and was a client-side fallback. New designs should not depend on either one.</p>
<h2>Translation and IPv6-only access</h2>
<p>When the access network is IPv6-only, IPv4 reachability has to come from somewhere. The main options:</p>
<ul>
<li><strong>NAT64 with DNS64</strong> (RFC 6146, RFC 6147) lets IPv6-only clients reach IPv4-only servers. A separate article in this series covers it.</li>
<li><strong>464XLAT</strong> (RFC 6877) adds a client-side translator, the CLAT, which converts IPv4 packets from the device's applications into IPv6, and a provider-side NAT64, the PLAT, which converts them back. It solves a problem plain NAT64 cannot: applications that use IPv4 literals or IPv4-only sockets still work on an IPv6-only network.</li>
<li><strong>DS-Lite</strong> (RFC 6333) tunnels IPv4 inside IPv6 from the customer's router (the B4) to a carrier-grade NAT (the AFTR). The customer gets native IPv6 and shared, translated IPv4.</li>
<li><strong>MAP-E</strong> (RFC 7597) and <strong>MAP-T</strong> (RFC 7599) do stateless IPv4-over-IPv6 mapping, where the IPv4 address and a port range are derived from the customer's IPv6 prefix, so the carrier does not hold per-flow state. <strong>lw4o6</strong> (RFC 7596) is a lighter variant with per-subscriber state in the provider's gateway.</li>
</ul>
<h2>Comparison</h2>
<table>
<thead>
<tr>
<th>Mechanism</th>
<th>Access network</th>
<th>Where state lives</th>
<th>Typical user</th>
</tr>
</thead>
<tbody><tr>
<td>Dual-stack</td>
<td>IPv4 and IPv6</td>
<td>Nowhere extra</td>
<td>Enterprises, servers, most ISPs</td>
</tr>
<tr>
<td>6in4</td>
<td>IPv4 only</td>
<td>Tunnel endpoints</td>
<td>Individuals, labs</td>
</tr>
<tr>
<td>6rd</td>
<td>IPv4 only</td>
<td>Stateless relay</td>
<td>ISPs</td>
</tr>
<tr>
<td>DS-Lite</td>
<td>IPv6 only</td>
<td>Carrier NAT (AFTR)</td>
<td>ISPs</td>
</tr>
<tr>
<td>MAP-E / MAP-T</td>
<td>IPv6 only</td>
<td>Stateless (mapping rules)</td>
<td>ISPs</td>
</tr>
<tr>
<td>464XLAT</td>
<td>IPv6 only</td>
<td>CLAT on device, NAT64 in network</td>
<td>Mobile carriers</td>
</tr>
</tbody></table>
<h2>What this means for a server operator</h2>
<p>If you run servers and not an access network, you will mostly care about two things.</p>
<p>First, <strong>publish IPv6 natively and keep IPv4 as well.</strong> Visitors on NAT64, 464XLAT, or DS-Lite networks reach IPv6 services directly, without translation, and that generally gives them the best path. A server with both an A and an AAAA record serves everybody.</p>
<p>Second, <strong>do not assume one address per user.</strong> Clients behind DS-Lite, MAP, and carrier-grade NAT share IPv4 addresses with many other users, so an IPv4 address is a poor identity for rate limiting or blocking. IPv6 clients are often easier to tell apart, though you should treat a /64 as the unit and not a single address, as discussed in the articles on IPv6 logging and neighbor tables.</p>
<p>You can see what a client's network is doing with a few checks:</p>
<pre><code>ping -6 -c 3 2001:db8::1             # is native IPv6 working?
curl -4 https://example.com/ -I      # does IPv4 still work?
dig AAAA ipv4only.arpa +short        # RFC 7050: a NAT64 prefix appears if DNS64 is present
</code></pre>
<p>The special name <code>ipv4only.arpa</code> is defined in RFC 7050 so that hosts can discover a NAT64 prefix. It has only IPv4 records, so any AAAA answer is synthesised by a DNS64 resolver.</p>
<h2>Choosing, in practice</h2>
<ul>
<li>Hosting a service: dual-stack, with correct AAAA records and no filtering of ICMPv6.</li>
<li>Connecting a lab without native IPv6: a 6in4 tunnel or a routed block over a VPN or BGP session.</li>
<li>Running an ISP or a campus: native dual-stack first; consider IPv6-only with NAT64 or 464XLAT when IPv4 address supply becomes the constraint.</li>
<li>Mobile deployments: 464XLAT is the standard answer to the "IPv4-only app on IPv6-only network" problem.</li>
</ul>
<p>Keep your own services reachable natively over both families, and the mechanism your visitors use will not matter.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[Reading traceroute and mtr Correctly: What the Hops Do and Do Not Tell You]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. traceroute and mtr…]]></description><link>https://ipye-com.hashnode.dev/reading-traceroute-and-mtr-correctly-what-the-hops-do-and-do-not-tell-you</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/reading-traceroute-and-mtr-correctly-what-the-hops-do-and-do-not-tell-you</guid><category><![CDATA[traceroute]]></category><category><![CDATA[Mtr]]></category><category><![CDATA[troubleshooting]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 16:27:44 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p><code>traceroute</code> and <code>mtr</code> are the first tools people reach for when something is slow or unreachable, and among the most misread. A hop with high latency or 100% loss looks like the culprit, yet often is not. This article explains how they work, how to read the output, and the IPv6 differences. Examples use <code>2001:db8::/32</code>, <code>192.0.2.0/24</code> and <code>203.0.113.0/24</code>, and the sample output is illustrative, not captured from a real network.</p>
<h2>How traceroute works</h2>
<p>Every IPv4 packet has a TTL (time to live) field, and every IPv6 packet has a Hop Limit field with the same role (RFC 8200). Each router decrements it by one, and if it reaches zero, the router discards the packet and sends back an ICMP Time Exceeded message (ICMPv4 type 11, ICMPv6 type 3). Traceroute sends probes with TTL 1, 2, 3 and so on and records who answers each. The source address of each Time Exceeded message identifies that hop. When a probe finally reaches the destination, the destination replies in the way the probe type dictates: with an ICMP Echo Reply for ICMP probes, an ICMP Port Unreachable for UDP probes to a closed port, or a TCP SYN-ACK or RST for TCP probes.</p>
<p>Consequences worth keeping in mind:</p>
<ul>
<li>Each answer comes from the router <strong>interface that received or generated the error</strong>, usually the ingress interface. You see one address per hop, not the whole device.</li>
<li>The reply path is the ordinary routing path back to you, and it may differ from the forward path.</li>
<li>Hops only appear if the router sends Time Exceeded. Many routers do not, or rate-limit it.</li>
</ul>
<h2>Common variants</h2>
<table>
<thead>
<tr>
<th>Tool and option</th>
<th>Probe type</th>
</tr>
</thead>
<tbody><tr>
<td><code>traceroute</code> (Linux default)</td>
<td>UDP to high ports</td>
</tr>
<tr>
<td><code>traceroute -I</code></td>
<td>ICMP Echo</td>
</tr>
<tr>
<td><code>traceroute -T -p 443</code></td>
<td>TCP SYN to the chosen port</td>
</tr>
<tr>
<td><code>traceroute -6</code> or <code>traceroute6</code></td>
<td>IPv6</td>
</tr>
<tr>
<td><code>mtr -r -w -c 100 host</code></td>
<td>Report mode, wide, 100 cycles</td>
</tr>
<tr>
<td><code>mtr -b -z</code></td>
<td>Show names with addresses, and the AS number</td>
</tr>
</tbody></table>
<p>Option names vary between implementations and versions, so check <code>man traceroute</code> on your system.</p>
<h2>Reading the output</h2>
<p>An illustrative mtr report:</p>
<pre><code>$ mtr -rwbzc 100 -6 2001:db8:200::10
HOST: host1                      Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. AS64496  gw.example.net       0.0%   100    0.4   0.5   0.3   1.1   0.1
  2. AS64500  ???                100.0    100    0.0   0.0   0.0   0.0   0.0
  3. AS64500  core2.example.net   62.0%   100   85.1  80.2  79.0  95.3   2.4
  4. AS64501  edge1.example.org    0.0%   100   81.0  80.9  80.2  84.0   0.6
  5. AS64501  2001:db8:200::10     0.0%   100   81.2  81.0  80.4  83.9   0.5
</code></pre>
<p>Hop 2 shows 100% loss, and hop 3 shows 62% loss, yet hops 4 and 5 show none. The rule is simple: <strong>loss that does not continue to the final hop is not real loss.</strong> The routers in hops 2 and 3 do not forward traffic differently, they just decline to answer probes aimed at their own control plane. The destination row is what counts, and here it is clean.</p>
<p>Conversely, if loss starts at a hop and <strong>persists in every later hop</strong>, including the destination, that is the place to look, since traffic really is being lost at or after that point. Latency follows the same logic: a hop with high latency followed by lower latency at later hops is slow at generating ICMP, not slow at forwarding.</p>
<h2>Why intermediate hops mislead</h2>
<ul>
<li><strong>Control-plane rate limiting.</strong> Time Exceeded is generated by the router's CPU, not its forwarding hardware, and routers deprioritise or rate-limit it. RFC 4443 requires ICMPv6 error rate limiting of this kind to be implemented.</li>
<li><strong>Asymmetric routing.</strong> The reply from hop N can return by a different path than the forward packets, so an unrelated return link can distort one hop's numbers. Ask for a traceroute from the other end.</li>
<li><strong>Load balancing.</strong> Routers split traffic across equal-cost paths using a hash that normally includes the addresses and ports. Classic traceroute varies the destination port per probe, so successive probes can follow different paths and the hops shown can come from several routers. Hop 5 may appear to come from router A and hop 6 from a router that is not downstream of A. Tools based on the Paris traceroute approach hold the flow fields constant to follow a single path.</li>
<li><strong>MPLS and tunnels.</strong> Hops inside an MPLS core or tunnel may be hidden or show unfamiliar addresses.</li>
<li><strong>Stars.</strong> A row of <code>* * *</code> means no answer within the timeout. If later hops answer, that router simply does not reply. If everything after a point is stars, either the probes or the replies are being dropped, or the path really ends there.</li>
</ul>
<h2>IPv6 specifics</h2>
<ul>
<li>The commands differ: <code>traceroute -6</code>, <code>traceroute6</code>, <code>mtr -6</code>, or <code>ping -6</code>, depending on the system.</li>
<li>IPv6 and IPv4 often take different paths to the same name, with different providers and different latency. Always test both explicitly, e.g. <code>mtr -4 example.net</code> and <code>mtr -6 example.net</code>.</li>
<li>Time Exceeded for IPv6 is ICMPv6 type 3, so a firewall that blocks it will make hops disappear (see the ICMPv6 reference in this series), and Packet Too Big (type 2) is a separate message you may meet when testing large probes.</li>
<li>Reverse DNS names for hops use <code>ip6.arpa</code>. Missing PTRs are normal and mean nothing about the path; <code>-n</code> skips lookups and makes the tool faster.</li>
</ul>
<h2>Practical method</h2>
<ol>
<li>Run it in both directions if you can, and in both IP versions.</li>
<li>Use a long run (<code>mtr -c 100</code> or more); a single sample says little about loss.</li>
<li>Compare the last hop against the previous ones. If the final hop is healthy, intermediate loss is a display artefact.</li>
<li>Use a probe type that resembles your traffic (<code>-T -p 443</code> for HTTPS).</li>
<li>Find the <strong>first hop where a problem begins and persists</strong>, identify its operator (<code>-z</code> adds AS numbers), and send them the full report with the source and destination addresses and the time of the test.</li>
</ol>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[Setting Up BIRD 2 for a Small ASN: A BGP Config with Filters]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. BIRD is a widely…]]></description><link>https://ipye-com.hashnode.dev/setting-up-bird-2-for-a-small-asn-a-bgp-config-with-filters</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/setting-up-bird-2-for-a-small-asn-a-bgp-config-with-filters</guid><category><![CDATA[bgp]]></category><category><![CDATA[bird]]></category><category><![CDATA[routing]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 16:20:12 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>BIRD is a widely used open-source routing daemon, common at internet exchanges and in small networks. This article builds a minimal BIRD 2 configuration for a small AS with one upstream, announcing one IPv4 and one IPv6 prefix, with import and export filters that keep you from leaking routes or accepting nonsense. A companion article in this series covers the same job in FRRouting. Examples use AS64496 (you), AS64511 (the upstream), <code>192.0.2.0/24</code> and <code>2001:db8:100::/48</code>. Treat it as a template and check it against the BIRD documentation for your version.</p>
<h2>The building blocks</h2>
<p>A BIRD configuration is made of <strong>protocols</strong>, each of which has one or more <strong>channels</strong> per address family. A few kinds matter here:</p>
<ul>
<li><code>device</code>: learns the interfaces and their addresses.</li>
<li><code>kernel</code>: exchanges routes with the operating system's forwarding table.</li>
<li><code>static</code>: originates routes you define by hand.</li>
<li><code>bgp</code>: a BGP session.</li>
</ul>
<p>BIRD 2 handles IPv4 and IPv6 in one daemon (BIRD 1 needed separate <code>bird</code> and <code>bird6</code> processes). A BGP session carries channels; <code>ipv4 { ... }</code> and <code>ipv6 { ... }</code> blocks inside the protocol say which families you exchange, and each channel has its own import and export filter.</p>
<h2>A complete minimal configuration</h2>
<pre><code>router id 192.0.2.1;

define MY_ASN  = 64496;
define UP_ASN  = 64511;

define MY_PREFIXES_V4 = [ 192.0.2.0/24 ];
define MY_PREFIXES_V6 = [ 2001:db8:100::/48 ];

protocol device { }

# Install only BGP-learned routes into the OS forwarding table.
protocol kernel kernel4 {
  ipv4 { import none; export where source = RTS_BGP; };
}

protocol kernel kernel6 {
  ipv6 { import none; export where source = RTS_BGP; };
}

# Originate our prefixes. 'blackhole' is a placeholder: the route exists
# only so the prefix can be exported to BGP. Real traffic is delivered by
# the more-specific connected routes on your LAN interfaces.
protocol static origin4 {
  ipv4;
  route 192.0.2.0/24 blackhole;
}

protocol static origin6 {
  ipv6;
  route 2001:db8:100::/48 blackhole;
}
</code></pre>
<p>The <code>export where source = RTS_BGP</code> line keeps the static origination routes out of the operating system's table, so they cannot override or shadow your real, more-specific routes. Only originate what you own or are authorised to announce: the prefix should have a matching ROA, and the filters below must agree with it.</p>
<h2>Filters</h2>
<p>Import filters protect you from the upstream; export filters protect the internet from you. BIRD filters are small programs that <code>accept</code> or <code>reject</code> a route. Define one pair per family:</p>
<pre><code>filter import_v6 {
  if net.len = 0 then reject;                      # no default route from BGP
  if net.len &gt; 48 then reject;                     # too specific
  if net ~ MY_PREFIXES_V6 then reject;             # never accept our own space
  if net ~ [ ::/8+, 2001:db8::/32+, fc00::/7+, fe80::/10+, ff00::/8+ ] then reject;
  if bgp_path.len &gt; 64 then reject;                # absurdly long path
  accept;
}

filter export_v6 {
  if net ~ MY_PREFIXES_V6 then accept;
  reject;
}
</code></pre>
<p>The IPv4 equivalents use <code>net.len &gt; 24</code> and a bogon set such as <code>[ 0.0.0.0/8+, 10.0.0.0/8+, 127.0.0.0/8+, 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 224.0.0.0/4+ ]</code>. The IPv6 example lists <code>2001:db8::/32</code> because it is a documentation range that should never appear in the real table. In this tutorial your own prefixes are also documentation space, so a literal copy of the filter would reject them on import (which is the desired behaviour for the real ones in your own space anyway). On a real network, substitute your actual allocation and a maintained bogon list.</p>
<p>The <code>+</code> suffix in a prefix set means "this prefix and all more specifics". The last filter in the chain is the important one: an export filter that ends in <code>reject</code> means a mistake elsewhere cannot cause you to export something by accident. This is the same principle of default-deny described in the BGP session checklist.</p>
<h2>The BGP session</h2>
<pre><code>protocol bgp upstream1_v6 {
  description "Upstream AS64511 (IPv6)";
  local 2001:db8:ffff::2 as MY_ASN;
  neighbor 2001:db8:ffff::1 as UP_ASN;

  ipv6 {
    import filter import_v6;
    export filter export_v6;
    import limit 500000 action restart;
  };
}

protocol bgp upstream1_v4 {
  description "Upstream AS64511 (IPv4)";
  local 198.51.100.2 as MY_ASN;
  neighbor 198.51.100.1 as UP_ASN;

  ipv4 {
    import filter import_v4;
    export filter export_v4;
    import limit 1000000 action restart;
  };
}
</code></pre>
<p>This uses one session per address family, which is simple to reason about and to debug. BGP can also carry both families over one session, and IPv4 routes can use an IPv6 next hop with the extended next-hop capability (RFC 8950), but both ends have to agree, so follow whatever your upstream supports. The limit values above are placeholders: set them comfortably above the number of routes you actually expect, as a safety net rather than a tight cap. If the upstream sends only a default route or a partial table, the limit and the "reject default" line need to change, so adapt the filters to what you actually receive.</p>
<h2>Check and apply</h2>
<pre><code>bird -p -c /etc/bird/bird.conf     # parse the config without running
birdc configure                    # reload the running daemon
birdc show protocols               # session state
birdc show route export upstream1_v6   # what we advertise
birdc show route protocol upstream1_v6 count
</code></pre>
<p><code>show protocols</code> should show <code>Established</code> for both sessions. Always inspect <code>show route export</code> before relying on the session: it should list your prefixes and nothing else. Then verify externally from a looking glass that the prefix appears with your origin AS.</p>
<h2>Adding RPKI validation</h2>
<p>BIRD 2 can validate routes with RPKI using an RTR session to a validator such as Routinator or StayRTR (RFC 8210 defines the RTR protocol). You define a <code>protocol rpki</code>, create ROA tables, and call <code>roa_check</code> in the import filter to reject invalid routes. The syntax changes between versions, so take the exact form from the BIRD documentation for your release.</p>
<h2>Operational habits</h2>
<ul>
<li>Keep the configuration in version control, and run <code>bird -p</code> before every reload.</li>
<li>Reload with <code>birdc configure</code> rather than restarting, so sessions survive.</li>
<li>Review the export filter whenever you add a prefix; a missing entry is the usual reason a prefix is not announced.</li>
<li>Monitor session state and route counts, as in the Prometheus article.</li>
</ul>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[IPv6 Neighbor Cache Exhaustion and the Risk of Scanning a /64]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. A standard IPv6…]]></description><link>https://ipye-com.hashnode.dev/ipv6-neighbor-cache-exhaustion-and-the-risk-of-scanning-a-64</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/ipv6-neighbor-cache-exhaustion-and-the-risk-of-scanning-a-64</guid><category><![CDATA[Security]]></category><category><![CDATA[networking]]></category><category><![CDATA[hosting]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[ndp]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 16:19:24 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>A standard IPv6 subnet is a /64, which holds 2^64 addresses. That size is often described as making address scanning impractical, and for brute-force scanning of a whole subnet from one place it largely does. But the same size creates a different problem on the router that serves the subnet: it has to resolve addresses on-link with Neighbor Discovery, and a flood of packets to addresses that do not exist can fill its neighbor cache. RFC 6583 ("Operational Neighbor Discovery Problems") describes this and is the best starting point. This article explains the mechanism, what it looks like in practice, and how to reduce the risk. Examples use <code>2001:db8:100::/48</code>.</p>
<h2>How the router resolves an on-link destination</h2>
<p>When a router receives a packet for an address inside a directly connected /64, it must find the link-layer address of the destination. It does so using Neighbor Solicitation and Neighbor Advertisement (RFC 4861):</p>
<ol>
<li>The router creates a neighbor cache entry in the INCOMPLETE state.</li>
<li>It sends Neighbor Solicitation messages to the solicited-node multicast address of the target.</li>
<li>If a Neighbor Advertisement arrives, the entry becomes REACHABLE and the packet is delivered. If not, after a limited number of retransmissions, the entry is removed and the packet is dropped (the router sends ICMPv6 Destination Unreachable, code 3, "address unreachable").</li>
</ol>
<p>Each attempted address therefore consumes a cache entry and generates multicast traffic for a short time. An attacker (or an unlucky scanner) that sends traffic to many addresses within your /64, nearly all of them unassigned, can create a very large number of INCOMPLETE entries. If the cache is a fixed size, legitimate entries may be evicted or new ones refused, and real hosts become intermittently unreachable. Some devices also exhibit high CPU use while processing the solicitations.</p>
<h2>What it looks like</h2>
<ul>
<li>Intermittent reachability for hosts in the subnet while the router CPU or neighbor-resolution activity is high.</li>
<li>A growing neighbor table dominated by INCOMPLETE or FAILED entries.</li>
<li>On Linux, kernel log messages saying the neighbor table overflowed.</li>
</ul>
<p>On a Linux router or host:</p>
<pre><code># count entries by state
ip -6 neigh show | awk '{print $NF}' | sort | uniq -c

# show only unresolved entries
ip -6 neigh show nud incomplete

# garbage-collection thresholds
sysctl net.ipv6.neigh.default.gc_thresh1 \
       net.ipv6.neigh.default.gc_thresh2 \
       net.ipv6.neigh.default.gc_thresh3
</code></pre>
<p><code>gc_thresh3</code> is the hard limit on the number of entries in the table. The default values are modest, intended for ordinary hosts, and a router for large subnets may need them raised. Check your kernel's defaults rather than assuming them.</p>
<h2>Is scanning a /64 realistic?</h2>
<p>Trying every address in a /64 is impractical, and that is true for scanners as much as for attackers. The cache problem above does not need a complete scan; it needs only enough distinct destinations to fill the table, which is a much smaller number. And scanners do not search at random. RFC 7707 ("Network Reconnaissance in IPv6 Networks") explains that real addresses are far from random: low-numbered interface identifiers (<code>::1</code>, <code>::2</code>, <code>::10</code>), addresses embedding an IPv4 address, patterns derived from MAC addresses (EUI-64), and addresses published in DNS, logs, or certificate transparency. Those make a targeted search feasible. The takeaway is not to depend on address obscurity for security; rely on a firewall.</p>
<h2>Mitigations</h2>
<p>RFC 6583 discusses these in more depth; the ones most useful to a small operator are:</p>
<p><strong>1. Do not give the router a huge on-link subnet if you can avoid it.</strong>
Route a /64 (or a smaller allocation) to each host or customer, with a next hop that is a single known address. The router then has a route to a specific address instead of resolving a vast on-link space. For example, route <code>2001:db8:100:10::/64</code> via the server's link address, and the router resolves only that one next-hop.</p>
<p><strong>2. Use /127 for point-to-point links.</strong>
RFC 6164 recommends /127 prefixes on router-to-router links, which avoids a ping-pong problem and also limits the neighbor-cache impact of scanning point-to-point link prefixes. Note that this is for router links, not general subnets, where /64 remains the norm. Reserve a /64 on paper and number the link as /127.</p>
<p><strong>3. Filter at the edge.</strong>
Only addresses that exist should be reachable. If infrastructure links should not be reachable from the internet, don't announce or route them, or drop traffic destined to them at the border with an ACL. Where a customer has just a few hosts in a /64, a firewall that allows only those destination addresses reduces the number of resolution attempts reaching the subnet. Stateless filters should still allow ICMPv6 needed for operation.</p>
<p><strong>4. Rate-limit and size the neighbor table.</strong>
Many router platforms let you limit the number of entries per interface, the rate of Neighbor Solicitations, or the number of incomplete entries. On Linux, raise <code>gc_thresh</code> values to match the subnet and, if needed, limit unsolicited traffic with nftables.</p>
<p><strong>5. Consider static or protocol-based population for critical addresses.</strong>
For a small number of important hosts, a static neighbor entry (<code>ip -6 neigh add 2001:db8:100:10::10 lladdr 02:00:00:00:00:10 dev eth1 nud permanent</code>) removes dependence on dynamic resolution, though it creates a maintenance burden if a NIC changes.</p>
<h2>Smaller prefixes are not a free fix</h2>
<p>Using a /112 or another subnet longer than /64 for hosts reduces the scan surface, but it breaks features that assume a 64-bit interface identifier, notably SLAAC (RFC 4862), and is discouraged for general LAN subnets. A /64 with good filtering and routed allocations is the norm; smaller on-link prefixes are most appropriate for links between routers.</p>
<h2>Quick checklist</h2>
<ul>
<li>Count neighbor entries by state on your routers and watch for growth.</li>
<li>Route per-host or per-customer allocations rather than exposing large on-link subnets.</li>
<li>Number router-to-router links with /127.</li>
<li>Filter traffic to unused addresses at the border where practical.</li>
<li>Raise and monitor neighbor table limits so that legitimate hosts are not evicted.</li>
<li>Never treat the size of a /64 as protection.</li>
</ul>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[Monitoring a BGP Session with Prometheus and Alerts]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. A BGP session can…]]></description><link>https://ipye-com.hashnode.dev/monitoring-a-bgp-session-with-prometheus-and-alerts</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/monitoring-a-bgp-session-with-prometheus-and-alerts</guid><category><![CDATA[monitoring]]></category><category><![CDATA[bgp]]></category><category><![CDATA[#prometheus]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 14:47:22 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>A BGP session can fail quietly. The peer resets, your prefix disappears from the internet, and you learn about it from a customer rather than a dashboard. Good monitoring watches three things: whether sessions are up, whether the number of prefixes each peer sends or receives is what you expect, and whether the rest of the world still sees your routes. This article shows how to export the first two to Prometheus from an FRR router and how to alert on all three. Examples use documentation values: AS64496 (you), AS64497 (upstream), <code>2001:db8:ffff::1</code> as the peer, and <code>2001:db8:100::/48</code> as your prefix.</p>
<h2>Choose a source of metrics</h2>
<p>There are two common routes:</p>
<ul>
<li><strong>A dedicated exporter.</strong> Community exporters exist for FRR (which reads from <code>vtysh</code>), BIRD, and GoBGP. They are convenient, but metric names differ between projects and versions, so look at the exporter's <code>/metrics</code> output and adapt the queries below accordingly.</li>
<li><strong>A small script with the node_exporter textfile collector.</strong> You control the metric names and the logic, and there is nothing extra to run. The rest of this article uses this approach.</li>
</ul>
<p>Start node_exporter with <code>--collector.textfile.directory=/var/lib/node_exporter/textfile</code>. Files there ending in <code>.prom</code> are exposed with the host's metrics.</p>
<h2>A textfile script for FRR</h2>
<p>FRR can print its summary as JSON: <code>vtysh -c 'show bgp summary json'</code>. The top-level keys are address families such as <code>ipv6Unicast</code>, each containing a <code>peers</code> object whose entries include fields like <code>state</code>, <code>pfxRcd</code>, and <code>pfxSnt</code>. Field names can differ between FRR releases, so run the command once and confirm them on your version before relying on this script:</p>
<pre><code>#!/bin/sh
OUT=/var/lib/node_exporter/textfile/bgp.prom
vtysh -c 'show bgp summary json' | jq -r '
  to_entries[]
  | select((.value|type)=="object" and (.value.peers != null))
  | .key as $afi
  | .value.peers | to_entries[]
  | "bgp_peer_established{afi=\"\($afi)\",peer=\"\(.key)\"} \(if .value.state=="Established" then 1 else 0 end)",
    "bgp_peer_prefixes_received{afi=\"\($afi)\",peer=\"\(.key)\"} \(.value.pfxRcd // 0)",
    "bgp_peer_prefixes_sent{afi=\"\($afi)\",peer=\"\(.key)\"} \(.value.pfxSnt // 0)"
' &gt; "$OUT.$$" &amp;&amp; mv "$OUT.$$" "$OUT"
</code></pre>
<p>Run it from cron or a systemd timer every minute. Writing to a temporary file and renaming it means Prometheus never scrapes a half-written file. The script requires <code>jq</code> and a user that may talk to FRR's sockets, for example a member of the <code>frrvty</code> group, or you can run it as root.</p>
<h2>Alert rules</h2>
<p>These rules use the metric names defined above plus the standard <code>node_textfile_mtime_seconds</code> metric that node_exporter creates for each textfile.</p>
<pre><code>groups:
- name: bgp
  rules:
  - alert: BgpSessionDown
    expr: bgp_peer_established == 0
    for: 5m
    labels: {severity: page}
    annotations:
      summary: "BGP peer {{ $labels.peer }} ({{ $labels.afi }}) is not Established"

  - alert: BgpSessionFlapping
    expr: changes(bgp_peer_established[30m]) &gt;= 4
    labels: {severity: warn}
    annotations:
      summary: "BGP peer {{ $labels.peer }} changed state several times in 30 minutes"

  - alert: BgpNoPrefixesReceived
    expr: bgp_peer_established == 1 and bgp_peer_prefixes_received == 0
    for: 10m
    labels: {severity: warn}

  - alert: BgpPrefixCountDropped
    expr: bgp_peer_prefixes_received &lt; 0.5 * (bgp_peer_prefixes_received offset 1h)
    for: 10m
    labels: {severity: warn}

  - alert: BgpNotAdvertising
    expr: bgp_peer_established == 1 and bgp_peer_prefixes_sent == 0
    for: 10m
    labels: {severity: page}

  - alert: BgpMetricsStale
    expr: time() - node_textfile_mtime_seconds{file="bgp.prom"} &gt; 300
    labels: {severity: warn}
</code></pre>
<p>Why these particular rules:</p>
<ul>
<li><strong><code>for: 5m</code></strong> on the down alert avoids paging for a session that resets and recovers by itself. Note that BGP's hold timer, by default 180 seconds in FRR, delays detection of a silently dead peer unless the link goes down or you use BFD, so a session can take minutes to report as down.</li>
<li><strong>Flapping</strong> is a state-change count over a window. Combined with the router's <code>bgp log-neighbor-changes</code> output, it points you to the reset reason.</li>
<li><strong>Zero prefixes received while Established</strong> usually means a policy problem on one side. A sudden drop to half or less can mean the upstream changed its filters or lost its own transit.</li>
<li><strong>Zero prefixes sent while Established</strong> means your own announcements have gone: the anchor route was removed, an outbound filter changed, or the network statement stopped matching. It deserves a page because it equals an outage.</li>
<li><strong>The stale-metrics rule</strong> protects against the most embarrassing failure of monitoring: a broken script that leaves the last values in place.</li>
</ul>
<p>The <code>offset 1h</code> comparison needs an hour of history and is naturally noisy for small tables, so tune the ratio to your peer. Peers with a stable table size are good candidates; a peer that sends only a default route should instead have an exact-count alert, such as <code>bgp_peer_prefixes_received != 1</code>.</p>
<h2>Add an outside view</h2>
<p>Everything above is your own router reporting about itself. If a filter at your upstream drops your prefix, your session still shows Established with prefixes sent. Complement the internal alerts with an external check that your prefix is visible:</p>
<ul>
<li>Query a public looking glass or a route collector API from a scheduled job and alert when your <code>2001:db8:100::/48</code> or <code>192.0.2.0/24</code> is absent, or has an unexpected origin ASN or an unexpected RPKI status.</li>
<li>Consider a BGP monitoring tool such as BGPalerter, an open-source monitor that consumes public route-collector feeds and can alert on hijacks, lost visibility, and RPKI changes for the prefixes you list.</li>
</ul>
<p>External checks are the only way to detect problems that happen beyond your edge.</p>
<h2>Dashboards and logs</h2>
<p>Graph <code>bgp_peer_established</code>, the received and sent counts, and the session uptime if you export it. Keep the router's BGP logs, especially neighbor-change and notification messages, in a central log system, because the Prometheus data tells you when something changed and the logs tell you why.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space. A /48 of IPv6 is free for the first year, with LOA, ROA, rDNS, and WHOIS handled for you. Locations are Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. To get in touch: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[PA, PI, or Leased Address Space: What Changes for Routing, RPKI, and Reverse DNS]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. When you need your…]]></description><link>https://ipye-com.hashnode.dev/pa-pi-or-leased-address-space-what-changes-for-routing-rpki-and-reverse-dns</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/pa-pi-or-leased-address-space-what-changes-for-routing-rpki-and-reverse-dns</guid><category><![CDATA[rpki]]></category><category><![CDATA[networking]]></category><category><![CDATA[ipv6]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 14:11:34 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>When you need your own IP addresses, there are three common ways to get them: take a block from your upstream provider (provider-assigned, PA), hold a block registered directly to you (provider-independent, PI), or lease a block from a holder who delegates it to you. The choice affects whom you depend on for routing, who can sign your RPKI records, and who can delegate your reverse DNS. This article compares them on those points only. Examples use documentation values: <code>2001:db8:100::/48</code>, <code>192.0.2.0/24</code>, and AS64496 (you) with AS64497 (an upstream).</p>
<p>A note on vocabulary: "PA" and "PI" are RIPE NCC terms, and policies differ among the five RIRs. ARIN, for instance, speaks of direct allocations and assignments versus reallocations and reassignments from an upstream. Eligibility rules change over time, so check your registry's current policy.</p>
<h2>The three models</h2>
<p><strong>Provider-assigned (PA).</strong> An ISP or LIR holds a larger allocation and gives you part of it. In the registry, the provider is the holder, and your block is a sub-assignment of theirs. The block is meant to be used with that provider. If you leave, you generally renumber.</p>
<p><strong>Provider-independent (PI) or direct assignment.</strong> The registry assigns the block to you, usually through a sponsoring LIR in the RIPE region or a direct agreement elsewhere. You are the registered holder, you can announce the block through any upstream, and it stays with you if you change providers. You also carry the obligations of a holder: contact data, fees to the registry or sponsor, and keeping registration accurate.</p>
<p><strong>Leased.</strong> A holder grants you the right to use and announce a block for a term. In the registry, the lessor typically remains the holder, and a WHOIS object marks your use of a sub-block. When the lease ends, the block goes back. Unlike PA, it is not tied to the network you connect through: you can announce it via any upstream that will carry it, subject to the lease terms and the lessor's authorization.</p>
<h2>Routing</h2>
<p>All three look the same once announced; BGP does not know how you obtained a prefix. What differs is who has to cooperate.</p>
<ul>
<li><strong>PA:</strong> your provider usually announces the covering aggregate, and your block is part of it. If you buy a second upstream, that second provider is asked to announce a block that belongs to someone else, which commonly requires the first provider's written authorization (a letter of authorization, LOA), proper IRR and RPKI data, and care about more-specific announcements. Many networks drop IPv4 routes longer than /24 and IPv6 routes longer than /48, so a PA block smaller than that may not propagate globally on its own.</li>
<li><strong>PI:</strong> you control the announcement. Each upstream filters customers by prefix, usually from IRR data and RPKI, and will want evidence that the block is yours. You need an ASN to originate it in your own name.</li>
<li><strong>Leased:</strong> you also need an origin ASN, which may be your own or one supplied with the lease. Upstreams typically ask for the LOA and check the same IRR and RPKI data. Confirm that the lessor will keep that authorization in place for the whole lease.</li>
</ul>
<h2>RPKI</h2>
<p>A Route Origin Authorization (ROA) can only be created by whoever controls the resource in the RIR's portal, in other words the registered holder. That determines who can make your announcements valid:</p>
<table>
<thead>
<tr>
<th>Model</th>
<th>Who creates the ROA</th>
<th>What it must name</th>
</tr>
</thead>
<tbody><tr>
<td>PA</td>
<td>The provider (the LIR), on request</td>
<td>The ASN that will originate, with a sensible maxLength</td>
</tr>
<tr>
<td>PI</td>
<td>You, in the RIR portal, or your sponsoring LIR</td>
<td>Your ASN</td>
</tr>
<tr>
<td>Leased</td>
<td>The lessor, on your behalf</td>
<td>The ASN you will originate from</td>
</tr>
</tbody></table>
<p>With PA, if you later move to another provider, the old ROA names the old origin ASN. An announcement from the new ASN will then be RPKI-invalid on networks that perform origin validation (RFC 6811) until the ROA is updated. The same applies at the end of a lease: the lessor should remove the ROA, and you should not announce once it ends. For a single /48, <code>maxLength 48</code> is the safest choice, because a forged more-specific announcement cannot validate against it.</p>
<h2>Reverse DNS</h2>
<p>Reverse DNS is delegated down the same chain as the address registration. For IPv6, delegation happens on nibble boundaries. Your <code>2001:db8:100::/48</code> corresponds to the zone <code>0.0.1.0.8.b.d.0.1.0.0.2.ip6.arpa</code>. For IPv4, a /24 maps to <code>2.0.192.in-addr.arpa</code>, and anything smaller needs classless delegation (RFC 2317).</p>
<ul>
<li><strong>PA:</strong> the provider holds the parent zone. They either run the PTR records for you or add NS records that delegate a zone to your servers.</li>
<li><strong>PI:</strong> you hold the registration, so you add the domain object or delegation yourself through the RIR, pointing at your nameservers.</li>
<li><strong>Leased:</strong> the lessor holds the registration, and requests the delegation on your behalf, so ask about turnaround time and how changes are made before you sign.</li>
</ul>
<p>Whichever model applies, verify the result with <code>dig -x 2001:db8:100::25</code> and <code>dig NS 0.0.1.0.8.b.d.0.1.0.0.2.ip6.arpa</code>, and make sure each PTR name has a matching forward record.</p>
<h2>WHOIS and IRR records</h2>
<p>An accurate WHOIS object (<code>inet6num</code> or <code>inetnum</code>, with contacts) and a matching IRR <code>route6</code> or <code>route</code> object are what upstreams check before accepting a prefix. Who may edit them follows the same pattern: the holder for PI, the provider for PA, and the lessor for leased space unless maintenance is delegated to you.</p>
<h2>Questions to settle before you commit</h2>
<ol>
<li>Who is the registered holder, and can you see the registry object?</li>
<li>Who creates and maintains the ROA, and how fast?</li>
<li>Who handles the rDNS delegation?</li>
<li>What is the block's history? Previously used space can carry blocklist entries, so check before use.</li>
<li>What happens at the end of the term: renumbering time, ROA removal, and any notice period?</li>
</ol>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space. A /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled for you. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[BGP Communities Explained: Well-Known Communities, Large Communities (RFC 8092), and Traffic Engineering for a Small ASN]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. A BGP community is a…]]></description><link>https://ipye-com.hashnode.dev/bgp-communities-explained-well-known-communities-large-communities-rfc-8092-and-traffic-engineering-for-a-small-asn</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/bgp-communities-explained-well-known-communities-large-communities-rfc-8092-and-traffic-engineering-for-a-small-asn</guid><category><![CDATA[Devops]]></category><category><![CDATA[bgp]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 14:01:08 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>A BGP community is a tag attached to a route. The tag does nothing by itself; it only matters because some router, somewhere, has a policy that matches it. For a small ASN, communities are the main way to ask an upstream to do something on your behalf, and the main way to label routes inside your own network. This article covers the three community types, the well-known values worth remembering, and a modest traffic-engineering approach. Examples use the documentation ASNs from RFC 5398: our network is AS64500, upstreams are AS64501 and AS64502, and the prefix is <code>192.0.2.0/24</code>.</p>
<h2>The three kinds of community</h2>
<ul>
<li><strong>Standard communities (RFC 1997):</strong> a 32-bit value, conventionally written as two 16-bit halves, <code>ASN:value</code>. The limitation is that the first half only fits a 2-byte ASN.</li>
<li><strong>Extended communities (RFC 4360):</strong> 8 bytes with a type field. They are used mostly by VPN and flow-spec features and are rarely needed for plain internet transit.</li>
<li><strong>Large communities (RFC 8092):</strong> 12 bytes, written as three 32-bit numbers: <code>Global Administrator:Local Data 1:Local Data 2</code>, for example <code>64500:1:64501</code>. The Global Administrator is a full 4-byte ASN, so networks with 32-bit ASNs finally have a proper namespace. RFC 8195 gives usage guidance, suggesting that the second field identifies a function and the third a parameter.</li>
</ul>
<p>All three are optional transitive attributes. They may travel through several networks, but nothing guarantees it: a network can strip or rewrite them, and some platforms only send them to a neighbor if you explicitly enable it. If a community seems to vanish, check the <code>send-community</code> equivalent on your side before blaming the upstream.</p>
<h2>Well-known communities</h2>
<p>A handful of values have fixed meaning and are defined in RFCs. In <code>ASN:value</code> form they live under <code>65535</code>:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td>NO_EXPORT (RFC 1997)</td>
<td><code>65535:65281</code></td>
<td>Do not advertise outside the local AS (or confederation)</td>
</tr>
<tr>
<td>NO_ADVERTISE (RFC 1997)</td>
<td><code>65535:65282</code></td>
<td>Do not advertise to any peer</td>
</tr>
<tr>
<td>NO_EXPORT_SUBCONFED (RFC 1997)</td>
<td><code>65535:65283</code></td>
<td>Do not advertise outside the confederation sub-AS</td>
</tr>
<tr>
<td>NO_PEER (RFC 3765)</td>
<td><code>65535:65284</code></td>
<td>Advisory: do not advertise to bilateral peers</td>
</tr>
<tr>
<td>BLACKHOLE (RFC 7999)</td>
<td><code>65535:666</code></td>
<td>Ask the receiver to discard traffic to this prefix</td>
</tr>
<tr>
<td>GRACEFUL_SHUTDOWN (RFC 8326)</td>
<td><code>65535:0</code></td>
<td>Lower preference before planned maintenance</td>
</tr>
</tbody></table>
<p>NO_EXPORT is handy when you want a neighbor to use a more-specific route but not spread it further. BLACKHOLE is the standard signal for remotely triggered blackholing during an attack. It is only useful if the receiving network supports it, and operators typically expect a single host route (/32 or /128) rather than a whole block, so read their documentation first.</p>
<h2>Communities are not authenticated</h2>
<p>Anyone can attach any community. A network that honors communities from customers must therefore apply them only to routes the customer is allowed to originate, and RFC 7454 (BCP 194) recommends scrubbing communities that fall in your own namespace on ingress, so neighbors cannot trigger your internal policy. Do the same for yourself: on routes learned from outside, remove any <code>64500:*:*</code> large communities before applying your own tags.</p>
<h2>What a small ASN can and cannot control</h2>
<p>Outbound traffic (what leaves you) is easy: you choose the exit with local preference. Inbound traffic (what reaches you) is decided by other networks, so you can only nudge it. The usual tools, roughly from weakest to strongest:</p>
<ol>
<li><strong>AS path prepending:</strong> make one path look longer. Weak, because many networks decide on local preference before path length, so a customer or peer route can win regardless.</li>
<li><strong>Provider action communities:</strong> ask an upstream to set a local preference, prepend toward a given neighbor, or withhold the route from certain peers. These are defined by each upstream and published in their documentation or IRR <code>aut-num</code> remarks. They are often more effective than prepending because they act inside the provider's policy.</li>
<li><strong>More-specific announcements:</strong> announce two halves of a block on different upstreams. Longest-prefix match wins, but global filters commonly drop anything longer than /24 for IPv4 or /48 for IPv6, and extra prefixes add routing-table entries for everyone.</li>
<li><strong>MED:</strong> only compared between routes from the same neighboring AS, so it helps with two links to one upstream and not with two different upstreams.</li>
</ol>
<h2>Tagging your own routes</h2>
<p>Define a small scheme and write it down. One workable layout using large communities, where the function is in field two (this scheme is invented for illustration; it is not a standard):</p>
<table>
<thead>
<tr>
<th>Community</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>64500:1:64501</code></td>
<td>Route learned from AS64501</td>
</tr>
<tr>
<td><code>64500:1:64502</code></td>
<td>Route learned from AS64502</td>
</tr>
<tr>
<td><code>64500:2:1</code></td>
<td>Originated by us</td>
</tr>
</tbody></table>
<p>Then export policy can say "send only routes tagged <code>64500:2:1</code> to upstreams", which protects you from accidentally becoming a transit path between your two providers (a route leak).</p>
<h2>A BIRD example</h2>
<pre><code>filter to_upstream_a {
  if net = 192.0.2.0/24 &amp;&amp; (64500, 2, 1) ~ bgp_large_community then {
    # hypothetical action community published by AS64501
    bgp_large_community.add((64501, 2, 64502));
    accept;
  }
  reject;
}

filter from_upstream_a {
  bgp_large_community.delete([(64500, *, *)]);  # scrub our namespace
  bgp_large_community.add((64500, 1, 64501));
  bgp_local_pref = 200;
  accept;  # prefix, bogon, and RPKI checks omitted here
}
</code></pre>
<p>The <code>(64501, 2, 64502)</code> value only works if AS64501 actually documents it; never assume another network's scheme. Real filters should also include prefix, bogon, and RPKI validation checks.</p>
<h2>Verify the effect</h2>
<p>After changing a community, check from outside: use a looking glass or RIPEstat to see whether the path through the targeted upstream changed. Change one thing at a time and record it. Convergence takes minutes, and some effects appear only in networks that actually honor the community.</p>
<h2>About IPYE</h2>
<p>IPYE (<a href="https://my.ipye.com">https://my.ipye.com</a>) leases IPv4, IPv6, and ASN space. A /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled for you. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[IPv6 Reverse DNS Explained: ip6.arpa, Nibbles, and Delegating Your /48]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. Reverse DNS (rDNS)…]]></description><link>https://ipye-com.hashnode.dev/ipv6-reverse-dns-explained-ip6-arpa-nibbles-and-delegating-your-48</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/ipv6-reverse-dns-explained-ip6-arpa-nibbles-and-delegating-your-48</guid><category><![CDATA[dns]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 13:40:28 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>Reverse DNS (rDNS) maps an IP address back to a name. It isn't glamorous, but mail servers, logging tools, traceroute readers, and abuse desks all lean on it. IPv6 reverse DNS looks intimidating at first because of the long <code>ip6.arpa</code> names. The rules are simple once you see the pattern, and delegation is the same idea you already know from forward DNS.</p>
<h2>How the name is built</h2>
<p>IPv4 reverse names flip the four decimal octets and append <code>in-addr.arpa</code>. IPv6 does the same at the level of <strong>nibbles</strong>: single hex digits (4 bits). To build the reverse name of an address:</p>
<ol>
<li>Write the address fully expanded, with no <code>::</code> shortening and all leading zeros: <code>2001:0db8:abcd:0001:0000:0000:0000:0010</code>.</li>
<li>Remove the colons: <code>20010db8abcd00010000000000000010</code> (32 hex digits).</li>
<li>Reverse the digits and put a dot between each one.</li>
<li>Append <code>ip6.arpa.</code></li>
</ol>
<p>The result for <code>2001:db8:abcd:1::10</code> is:</p>
<pre><code>0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.
</code></pre>
<p>You rarely need to do this by hand. <code>dig -x 2001:db8:abcd:1::10</code> does it, and so does Python:</p>
<pre><code class="language-python">import ipaddress
a = ipaddress.ip_address("2001:db8:abcd:1::10")
print(a.reverse_pointer)
</code></pre>
<h2>The zone for a /48</h2>
<p>A reverse zone covers a prefix. Each nibble of prefix length adds one label, so a /48 (12 nibbles) is a zone with 12 labels before <code>ip6.arpa</code>. For <code>2001:db8:abcd::/48</code>:</p>
<pre><code>d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.
</code></pre>
<p>The first 12 hex digits <code>2001 0db8 abcd</code>, reversed. Everything below that zone name, the other 20 nibbles, is yours to define.</p>
<h2>Who delegates what</h2>
<p>DNS delegation is by NS records in the parent zone. For your space, the chain runs from <code>ip6.arpa</code> down through the RIR and, depending on how you got your space, a provider or LIR, to you:</p>
<ul>
<li><strong>If you hold the space directly</strong>, you ask your RIR (or the party that manages the address-space record) to publish NS records for your reverse zone pointing at your name servers.</li>
<li><strong>If you lease or sub-allocate space</strong>, the lessor either publishes the delegation for you or maintains the PTR records on your behalf. Ask which model they support and how requests are made.</li>
</ul>
<p>Either way you need working authoritative name servers (BIND, NSD, Knot, PowerDNS, or a hosted DNS service that supports reverse zones) before delegation is useful. Plan for at least two servers on different networks.</p>
<h2>Delegation works on nibble boundaries</h2>
<p>DNS zone cuts happen at label boundaries, and each label is one nibble. That means clean reverse delegation exists for prefix lengths that are multiples of 4: /32, /36, /40, /44, /48, /52, /56, /60, /64. A /47 or /53 doesn't match a single zone. It has to be split into several delegations (a /47 becomes two /48 zones). This is why I recommend subnetting on nibble boundaries from the start.</p>
<h2>A minimal zone file</h2>
<p>For <code>d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.</code> in BIND format:</p>
<pre><code>$TTL 3600
@   IN SOA ns1.example.net. hostmaster.example.net. (
        2026102601 ; serial
        3600       ; refresh
        900        ; retry
        1209600    ; expire
        3600 )     ; negative TTL
    IN NS  ns1.example.net.
    IN NS  ns2.example.net.

; 2001:db8:abcd:1::10
0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0  IN PTR web1.example.net.
</code></pre>
<p>Inside the zone, the owner name is the remaining 20 nibbles, reversed, without the zone suffix. The matching delegation in the parent zone is just NS records:</p>
<pre><code>d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.  IN NS  ns1.example.net.
d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.  IN NS  ns2.example.net.
</code></pre>
<h2>Generate PTRs from a list</h2>
<p>Writing 20-nibble labels by hand invites typos. Generate them:</p>
<pre><code class="language-python">import ipaddress
zone_net = ipaddress.ip_network("2001:db8:abcd::/48")
zone_suffix = zone_net.network_address.reverse_pointer.split(".", 20)[20]
hosts = {"2001:db8:abcd:1::10": "web1.example.net.",
         "2001:db8:abcd:1::11": "mail.example.net."}
for addr, name in hosts.items():
    ptr = ipaddress.ip_address(addr).reverse_pointer
    label = ptr[: -len(zone_suffix) - 1]
    print(f"{label}  IN PTR {name}")
</code></pre>
<p>Keep the host list in version control and regenerate the zone, bumping the serial.</p>
<h2>Check your work</h2>
<ul>
<li><code>dig NS d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa</code> should return your name servers.</li>
<li><code>dig -x 2001:db8:abcd:1::10 +short</code> should return the name.</li>
<li>Query the authoritative servers directly (<code>dig @ns1.example.net -x ...</code>) to separate delegation problems from zone problems.</li>
<li><strong>Forward-confirm it:</strong> the PTR name should have an AAAA record pointing back to the same address (forward-confirmed reverse DNS). Mail systems and some security tools check for this.</li>
</ul>
<h2>Practical advice</h2>
<ul>
<li><strong>You don't need a PTR for every address.</strong> A /64 holds 2^64 of them. Publish PTRs for servers, mail relays, and anything people see in logs or traceroutes. Some operators generate generic names for dynamic pools; do that with a script rather than by hand.</li>
<li><strong>Match your naming across families.</strong> If the IPv4 PTR says <code>mail.example.net</code>, make the IPv6 PTR say the same and give it an AAAA.</li>
<li><strong>Mind TTLs.</strong> Short TTLs make changes quick, but values around an hour are fine for static hosts.</li>
<li><strong>DNSSEC is optional.</strong> If you sign the zone, the parent zone needs a DS record for your key.</li>
<li><strong>Delegation errors are quiet.</strong> A lame delegation (NS records pointing at a server that doesn't answer for the zone) shows up as failed lookups, so test it from the outside after any change.</li>
</ul>
<h2>About IPYE</h2>
<p>IPYE leases IPv4, IPv6, and ASN space and sells server+IP bundles. A /48 of IPv6 is free for the year; a /44 is $20/yr and a /40 is $100/yr; an IPv4 /24 is $160/mo. LOA, ROA, rDNS, and WHOIS are handled for you. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Details: <a href="https://my.ipye.com/products/ipv6-rental">IPv6 rental</a>, <a href="https://my.ipye.com/products/ipv4-rental">IPv4 rental</a>, <a href="https://my.ipye.com/products/server-ip-bundles">server+IP bundles</a>. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[RPKI ROAs in Plain English: What They Do and the maxLength Mistakes That Bite]]></title><description><![CDATA[Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking. If you announce your…]]></description><link>https://ipye-com.hashnode.dev/rpki-roas-in-plain-english-what-they-do-and-the-maxlength-mistakes-that-bite</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/rpki-roas-in-plain-english-what-they-do-and-the-maxlength-mistakes-that-bite</guid><category><![CDATA[rpki]]></category><category><![CDATA[bgp]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[networking]]></category><category><![CDATA[routing-security]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 13:06:51 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.</em></p>
<p>If you announce your own prefix from your own ASN, sooner or later a transit provider's route filter will ask a simple question: "does a signed record say this ASN may originate this prefix?" That record is a Route Origin Authorization, or ROA. This article covers what a ROA contains, how routers use it, and the maxLength mistakes I see most often.</p>
<h2>What a ROA actually says</h2>
<p>A ROA is a small signed object in the RPKI (Resource Public Key Infrastructure). It contains three things:</p>
<ol>
<li><strong>A prefix</strong>, for example <code>2001:db8:abcd::/48</code> (a documentation prefix, used here for illustration).</li>
<li><strong>A maximum length</strong> (<code>maxLength</code>), the longest more-specific the origin is authorized to announce.</li>
<li><strong>An origin ASN</strong>, for example <code>AS64496</code> (also a documentation ASN).</li>
</ol>
<p>Read it as: "AS64496 is authorized to originate 2001:db8:abcd::/48, and any more-specific of it up to the maxLength." The ROA is issued by whoever holds the address space, through their RIR's RPKI system (or their own CA). This matters when you lease space: the holder creates the ROA for <em>your</em> ASN, because you can't sign for space you don't hold.</p>
<h2>How routers use it: three states</h2>
<p>Networks that do route origin validation (ROV, RFC 6811) compare each BGP announcement to the validated ROA data and classify it:</p>
<ul>
<li><strong>Valid:</strong> a ROA covers the prefix, the origin ASN matches, and the prefix length is ≤ maxLength.</li>
<li><strong>Invalid:</strong> at least one ROA covers the prefix, but either the origin ASN doesn't match or the announced prefix is longer than maxLength.</li>
<li><strong>NotFound:</strong> no ROA covers the prefix at all.</li>
</ul>
<p>Many networks drop Invalid routes. NotFound is usually still accepted, which is why unsigned prefixes mostly work today. The practical lesson: a <em>wrong</em> ROA is worse than <em>no</em> ROA, because Invalid gets dropped while NotFound usually doesn't.</p>
<h2>Mistake 1: maxLength set too long</h2>
<p>The tempting configuration is a ROA for a /44 with maxLength 48, "just in case I want to split it later." RFC 9319 (BCP 185), the guidance on maxLength, recommends against this. A ROA that authorizes lots of unannounced more-specifics lets an attacker announce a more-specific with a <em>forged</em> origin (your ASN prepended) and still validate as Valid. Longest-prefix-match then pulls traffic to the attacker.</p>
<p>The conservative rule: <strong>set maxLength equal to the prefix length you actually announce.</strong> If you announce one /48, publish a /48 ROA with maxLength 48. If you announce a /44 and also four /46s, publish ROAs for exactly those, not one broad ROA.</p>
<h2>Mistake 2: forgetting the more-specifics you announce</h2>
<p>The opposite problem: you publish a ROA for <code>/44, maxLength 44</code>, then announce two /45s for traffic engineering. Both are longer than maxLength, so both are <strong>Invalid</strong> and get dropped by ROV networks, while the /44 still works. Every distinct prefix you originate needs a ROA entry that covers it at that length. Before announcing anything, write down every prefix and length you plan to originate, then check that each has a matching ROA.</p>
<h2>Mistake 3: origin ASN mismatch</h2>
<p>Common triggers: you changed ASNs but the ROA still lists the old one, or a provider announces on your behalf during a migration from an ASN that isn't on the ROA. A stale ROA for some other ASN doesn't hurt you as long as yours also exists, but if yours is missing, your announcement is Invalid, not NotFound. If more than one ASN legitimately originates the prefix, publish a ROA for each. Also check IPv4 and IPv6 separately: ROAs are per prefix, and it's easy to fix one family and forget the other.</p>
<h2>Mistake 4: expecting instant effect</h2>
<p>ROA changes don't take effect globally the moment you click save. RPKI validators fetch repository data on a schedule, then push validated payloads to routers. Allow time (often minutes, sometimes an hour or more) before blaming your config. If you're swapping ROAs, <strong>create the new one first, wait until it validates, then remove the old one.</strong></p>
<h2>A short verification routine</h2>
<p>Before and after a change:</p>
<ol>
<li><strong>List the prefixes you will originate</strong> and their lengths.</li>
<li><strong>Check the ROA set</strong> in your RIR's RPKI dashboard (or your lessor's portal) against that list.</li>
<li><strong>Validate from the outside.</strong> Public tools such as RIPEstat's RPKI validation widget, bgp.tools, or a looking glass of a network that runs ROV show you the status as the world sees it. If you run your own validator (Routinator, rpki-client, and others), you can query it directly.</li>
<li><strong>Confirm the route is seen</strong> at a few vantage points (a route collector like RIPE RIS or RouteViews) and the origin AS is yours.</li>
<li><strong>Re-check after any renumbering, ASN change, or new announcement.</strong></li>
</ol>
<h2>One more tool: AS0 ROAs</h2>
<p>RFC 6483 defines ROAs with origin AS0, meaning "nobody is authorized to originate this prefix." Holders can use them for space they don't intend to announce, so any announcement of it is Invalid. Remember to replace one with a normal ROA before you start announcing.</p>
<h2>ROAs vs IRR</h2>
<p>ROAs and IRR <code>route6</code> objects overlap but aren't the same: IRR data drives prefix-list generation at many providers, while RPKI drives origin validation. Publish both and keep them consistent.</p>
<h2>About IPYE</h2>
<p>IPYE leases IPv4, IPv6, and ASN space and sells server+IP bundles. A /48 of IPv6 is free for the year; a /44 is $20/yr and a /40 is $100/yr; an IPv4 /24 is $160/mo. LOA, ROA, rDNS, and WHOIS are handled for you. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Details: <a href="https://my.ipye.com/products/ipv6-rental">IPv6 rental</a>, <a href="https://my.ipye.com/products/ipv4-rental">IPv4 rental</a>, <a href="https://my.ipye.com/products/server-ip-bundles">server+IP bundles</a>. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
<p><em>Disclosure: I run IPYE</em></p>
]]></content:encoded></item><item><title><![CDATA[A checklist for announcing a leased IPv6 prefix from your own ASN]]></title><description><![CDATA[You have an ASN and you have just been handed an IPv6 block to announce. Before you advertise it, here is the short checklist I run through. The holder of…]]></description><link>https://ipye-com.hashnode.dev/a-checklist-for-announcing-a-leased-ipv6-prefix-from-your-own-asn</link><guid isPermaLink="true">https://ipye-com.hashnode.dev/a-checklist-for-announcing-a-leased-ipv6-prefix-from-your-own-asn</guid><category><![CDATA[bgp]]></category><category><![CDATA[ipv6]]></category><category><![CDATA[networking]]></category><category><![CDATA[infrastructure]]></category><dc:creator><![CDATA[IPYE]]></dc:creator><pubDate>Mon, 26 Oct 2026 00:18:23 GMT</pubDate><content:encoded><![CDATA[<p>You have an ASN and you have just been handed an IPv6 block to announce. Before you advertise it, here is the short checklist I run through.</p>
<h2>1. Get the authorization in writing</h2>
<p>The holder of the block should give you a letter of authorization (LOA) that names your ASN and the prefix. Your upstream will usually ask for it before they accept the announcement.</p>
<h2>2. Publish a ROA</h2>
<p>A Route Origin Authorization tells the world that your ASN is allowed to originate the prefix. Networks that do RPKI route origin validation will otherwise treat your announcement as unknown or invalid. Make sure the max length matches what you really announce (a /48 ROA for a /48 announcement).</p>
<h2>3. Create the route6 object</h2>
<p>Add a route6 object in an IRR database your upstreams read, with your ASN as the origin. Many providers build their prefix filters from IRR data, so a missing object means a filtered prefix.</p>
<h2>4. Announce the right size</h2>
<p>Most networks accept IPv6 prefixes up to /48 and drop anything more specific. A /48 holds 65,536 /64 subnets, which is plenty for a lab or a small site.</p>
<h2>5. Fix reverse DNS and WHOIS</h2>
<p>Set up rDNS delegation for your blocks and make sure the WHOIS contact data points at you, not at the previous holder.</p>
<h2>6. Verify from outside</h2>
<p>Check the announcement from a public looking glass and confirm the ROA shows as valid. Test from two different networks before you rely on it.</p>
<p>If you do not have a block yet: I run IPYE (disclosure: my company). We lease IPv4 and IPv6 space that you announce from your own ASN. A /48 of IPv6 is free for the year, and we handle the LOA, ROA, rDNS and WHOIS changes described above. Details and pricing for IPv6 are at <a href="https://my.ipye.com/products/ipv6-rental">https://my.ipye.com/products/ipv6-rental</a> and for IPv4 at <a href="https://my.ipye.com/products/ipv4-rental">https://my.ipye.com/products/ipv4-rental</a>. Questions: <a href="mailto:ipye@turnel.com">ipye@turnel.com</a>.</p>
]]></content:encoded></item></channel></rss>