Hello BIRD maintainers,
### Summary
BIRD appears to miss the mandatory RFC 7607 validation for AS 0 in received
BGP OPEN messages when the peer is configured in accept-any external-AS
mode, including dynamic BGP peers created from a `neighbor range ...
external` configuration.
RFC 7607 Section 2 says that AS 0 is reserved, must not be used by a BGP
speaker, and must not be accepted in a BGP OPEN message. When a BGP speaker
receives an OPEN whose peer AS is 0, it must abort the connection and send
an OPEN Message Error with subcode Bad Peer AS.
In the tested BIRD configuration, a dynamic external peer was able to
complete session establishment while claiming peer AS 0.
### Affected Configuration
This issue is relevant when BIRD is configured to accept any external AS,
for example:
```bird
protocol bgp as0_open_test {
local as 65001;
neighbor 10.0.0.2 external;
ipv4 { import all; export none; };
}
```
or with dynamic BGP peers:
```bird
protocol bgp dyn_as0_test {
local as 65001;
neighbor range 10.100.0.0/24 external;
ipv4 { import all; export none; };
}
```
The dynamic-peer case was tested locally.
### Expected Behavior
If a peer sends a BGP OPEN with My Autonomous System set to 0, BIRD should
reject the OPEN, abort the connection, and send:
```text
Error Code: OPEN Message Error
Error Subcode: Bad Peer AS
```
That is, BIRD should send NOTIFICATION 2/2 rather than allowing the BGP FSM
to reach Established.
### Actual Behavior
With a dynamic external peer configuration, BIRD accepted an incoming OPEN
with peer AS 0 and established the session.
`birdc show protocols all` showed the spawned dynamic BGP instance in
Established state:
```text
as0_dyn_1 BGP --- up ... Established
BGP state: Established
Neighbor address: 10.100.0.2
Neighbor AS: 0
Local AS: 65001
Neighbor ID: 10.0.0.2
```
The BIRD log also showed the AS 0 OPEN being accepted and the session
becoming established:
```text
as0_dyn_1: Got OPEN(as=0,hold=180,id=10.0.0.2)
as0_dyn_1: Sending OPEN(ver=4,as=65001,hold=240,id=0a000001)
as0_dyn_1: Sending KEEPALIVE
as0_dyn_1: Got KEEPALIVE
as0_dyn_1: BGP session established
```
For comparison, FRR rejects the same OPEN with NOTIFICATION 2/2.
### Root Cause
The relevant validation is in `bgp_rx_open()` in `proto/bgp/packets.c`.
For accept-any external-AS mode, where the configured remote AS is
unspecified, the current check rejects a peer only when the effective peer
AS equals the local AS. There does not appear to be a separate check for
the reserved value 0.
The effective logic is:
```c
if (caps->as4_support) {
u32 as4 = caps->as4_number;
if (p->remote_as ? (as4 != p->remote_as) : (as4 == p->local_as))
bgp_error(conn, 2, 2, ...);
conn->received_as = as4;
} else {
if (p->remote_as ? (asn != p->remote_as) : (asn == p->local_as))
bgp_error(conn, 2, 2, ...);
conn->received_as = asn;
}
```
In accept-any external mode, `asn == 0` is not equal to the non-zero local
AS, so it can pass this validation and become `conn->received_as`.
### AS4 Capability Case
The AS4 Capability path should also be considered. If the OPEN carries AS4
Capability and the AS4 number is 0, that effective peer AS should also be
rejected.
A fix should therefore reject both cases:
```c
if (asn == 0)
reject with OPEN Message Error / Bad Peer AS;
if (caps->as4_support && caps->as4_number == 0)
reject with OPEN Message Error / Bad Peer AS;
```
### Impact
This is best described as an RFC 7607 compliance bug in BGP OPEN validation
for accept-any external and dynamic peers.
Practical impact depends on deployments using accept-any external-AS or
dynamic BGP peering, but the observed behavior can:
1. Allow an external peer to establish a session while claiming the
reserved AS number 0.
2. Violate RFC 7607's mandatory OPEN handling.
3. Create inconsistent peer-AS state for logging, policy, and later route
processing.
4. Cause interoperability issues with implementations that correctly reject
AS 0.
The issue does not require a configured neighbor AS of 0. It occurs in
accept-any external-AS mode, where BIRD accepts an external peer AS
dynamically.
### Version Tested
This was reproduced against:
```text
BIRD version 2.19.0+branch.master.880200b1f94c
```
Best regards,
Xinzhe Liu