Project

General

Profile

Actions

Bug #17039

open

NAT64 fails when PPPoE interface address is also configured as a CARP VIP on another interface

Added by Bert Smith 2 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
PPP Interfaces
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:
Plus Target Version:
Release Notes:
Default
Affected Version:
2.9.0
Affected Architecture:

Description

There are two related issues involved.

pfSense has an existing address-discovery problem when an IPv4 address is simultaneously the actual address of a PPPoE interface and a CARP VIP on another interface. This behavior already existed in 2.8.1 and affected other functionality, but NAT64 continued to work in 2.8.1.

In 2.9.0, NAT64 now fails because its source-address resolution encounters this existing problem.
The underlying PPPoE/VIP address-discovery problem therefore predates 2.9.0, while the NAT64 failure is a 2.9.0 regression.

ENVIRONMENT

pfSense CE 2.9.0-RELEASE
amd64
FreeBSD 16.0-CURRENT
Build: RELENG_2_9_0-n256132-d8e3138ecf52

NETWORK TOPOLOGY

The ISP provisions the connection as follows.
  • The Internet connection terminates as a PPPoE session on pppoe0.
  • pppoe0 has IPv4 address 11.22.33.65/32.
  • The ISP routes 11.22.33.64/28 through the PPPoE session.
  • There is no separate WAN interface for this routed /28.
  • OPT2 carries the routed /28 internally.
  • OPT2 has primary address 192.168.67.1.
  • 11.22.33.65 is configured as a CARP VIP on OPT2.

Other hosts on the routed network use addresses such as 11.22.33.66, 11.22.33.67, etc.

Therefore 11.22.33.65 legitimately exists in two contexts:
  • pppoe0: 11.22.33.65/32, actual PPPoE interface address
  • OPT2: 192.168.67.1 primary address, with 11.22.33.65 as a CARP VIP
    This is intentional and required by the ISP's routing model.

EXISTING ADDRESS-RESOLUTION PROBLEM

The PPPoE address is correctly returned by the lower-level interface-address API.
Command:
php -r 'require_once("config.inc"); require_once("interfaces.inc"); var_dump(pfSense_get_ifaddrs("pppoe0"));'
The result includes:
["addrs"] =>
array(1) {
[0] =>
array(4) {
["addr"] => string(13) "11.22.33.65"
["subnetbits"] => int(32)
["subnet"] => string(15) "255.255.255.255"
["dstaddr"] => string(13) "78.33.253.139"
}
}

However:

php -r 'require_once("config.inc"); require_once("interfaces.inc"); var_dump(get_interface_addresses("pppoe0"));'
does not return an ipaddr field.

Consequently:
php -r 'require_once("config.inc"); require_once("interfaces.inc"); var_dump(get_interface_ip("opt5"));'
returns:
NULL

CAUSE

get_interface_addresses() builds a global list of configured IPv4 VIP addresses.
The relevant code is:
$v4vips = array();
foreach (array_keys(get_configured_vip_list()) as $viface) {
$vip = get_configured_vip($viface);
if (is_ipaddrv4($vip['subnet'])) {
array_push($v4vips, $vip['subnet']);
}
}

It then filters the addresses returned for the interface:
$v4addrs = array_filter($ifaddrs['addrs'], function($addr) use ($v4vips){
return (array_search($addr['addr'], $v4vips) === false);
});

The configured VIP list contains 11.22.3365 because it is a CARP VIP on OPT2.
When processing pppoe0, the same address is therefore removed from the list of actual addresses belonging to pppoe0.
The filtering does not appear to distinguish which interface owns the VIP.
As a result:
pfSense_get_ifaddrs("pppoe0") correctly finds 11.22.33.65.
get_interface_addresses("pppoe0") filters it out.
get_interface_ip("opt5") returns NULL.

VERSION COMPARISON

pfSense 2.8.1:
The underlying PPPoE/VIP address-resolution problem already existed.
For this configuration, get_interface_ip("opt5") could fail to resolve the PPPoE address, affecting other pfSense functionality that relied on the common interface-address API.
However, NAT64 still worked in 2.8.1.

pfSense 2.9.0:
  • After upgrading to 2.9.0, NAT64 no longer works.
  • The NAT64 rule remains present in the GUI but shows zero hits.
  • The generated rules contain messages such as:
  • Could not determine NAT64 source address - Allow NAT64 traffic
  • There is no corresponding NAT64 translation rule in pfctl.
  • The affected NAT rule uses opt5ip as its source.
  • Changing the rule to use an address/interface that does not encounter this address-resolution problem causes the NAT64 rule to be generated and traffic counters to increase.

IMPACT

The immediate regression in 2.9.0 is that NAT64 no longer works when using the PPPoE interface address as the NAT source.
The underlying address-resolution problem can also affect other pfSense functionality using get_interface_ip().
This does not appear to be a NAT64 configuration problem. The lower-level interface-address API correctly discovers the PPPoE address; the address is subsequently discarded by get_interface_addresses() because it also exists as a VIP on another interface.

EXPECTED BEHAVIOR

When obtaining the addresses of an interface, a VIP configured on another interface should not cause an identical address that is actually assigned to the queried interface to be discarded.
Specifically:
get_interface_addresses("pppoe0")
should return an ipaddr of:
11.22.33.65
and:
get_interface_ip("opt5")
should return:
11.22.33.65
The presence of 11.22.33.65 as a CARP VIP on OPT2 should not prevent it from being recognized as the actual address of pppoe0.

ACTUAL BEHAVIOR

pfSense_get_ifaddrs("pppoe0")
11.22.33.65

get_interface_addresses("pppoe0")
no ipaddr

get_interface_ip("opt5")
NULL

NAT64 in 2.9.0
cannot determine source address
NAT64 translation rule is not generated

SUGGESTED FIX

The VIP filtering in get_interface_addresses() should be made interface-aware.
An address should not be discarded merely because the same address exists somewhere in the global VIP list. In particular, an address that is actually assigned to the interface being queried must remain available as that interface's address.
The fix should preserve the existing behavior of excluding VIP addresses where appropriate, while avoiding the removal of an address that is simultaneously a legitimate address of another interface.

No data to display

Actions

Also available in: Atom