networkd: allow setting rp_filter for an interface

This commit is contained in:
Susant Sahani 2023-07-13 21:40:48 +05:30
parent afe7026511
commit 9c72e8f8bc
6 changed files with 60 additions and 0 deletions

View file

@ -776,6 +776,22 @@ Table=1234</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv4ReversePathFilter=</varname></term>
<listitem>
<para>Configure IPv4 Reverse Path Filtering. If enabled, when an IPv4 packet is received, the machine will first check
whether the <emphasis>source</emphasis> of the packet would be routed through the interface it came in. If there is no
route to the source on that interface, the machine will drop the packet. Takes one of
<literal>no</literal>, <literal>strict</literal>, or <literal>loose</literal>. When <literal>no</literal>,
no source validation will be done. When <literal>strict</literal>, mode each incoming packet is tested against the FIB and
if the incoming interface is not the best reverse path, the packet check will fail. By default failed packets are discarded.
When <literal>loose</literal>, mode each incoming packet's source address is tested against the FIB. The packet is dropped
only if the source address is not reachable via any interface on that router.
See <ulink url="https://tools.ietf.org/html/rfc1027">RFC 3704</ulink>.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv4AcceptLocal=</varname></term>
<listitem>

View file

@ -140,6 +140,7 @@ Network.PrimarySlave, config_parse_bool,
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter)
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0

View file

@ -474,6 +474,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.ipv6_hop_limit = -1,
.ipv6_proxy_ndp = -1,
.proxy_arp = -1,
.ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
.ipv6_accept_ra = -1,
.ipv6_accept_ra_use_dns = true,

View file

@ -307,6 +307,7 @@ struct Network {
int proxy_arp;
uint32_t ipv6_mtu;
IPv6PrivacyExtensions ipv6_privacy_extensions;
IPReversePathFilter ipv4_rp_filter;
int ipv6_proxy_ndp;
Set *ipv6_proxy_ndp_addresses;

View file

@ -89,6 +89,21 @@ static int link_set_ipv6_forward(Link *link) {
return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
}
static int link_set_ipv4_rp_filter(Link *link) {
assert(link);
if (link->flags & IFF_LOOPBACK)
return 0;
if (!link->network)
return 0;
if (link->network->ipv4_rp_filter < 0)
return 0;
return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter);
}
static int link_set_ipv6_privacy_extensions(Link *link) {
IPv6PrivacyExtensions val;
@ -302,6 +317,10 @@ int link_set_sysctl(Link *link) {
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv4 route_localnet flag for interface, ignoring: %m");
r = link_set_ipv4_rp_filter(link);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m");
/* If promote_secondaries is not set, DHCP will work only as long as the IP address does not
* changes between leases. The kernel will remove all secondary IP addresses of an interface
* otherwise. The way systemd-networkd works is that the new IP of a lease is added as a
@ -325,3 +344,13 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExte
IPV6_PRIVACY_EXTENSIONS_YES);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_privacy_extensions, ipv6_privacy_extensions, IPv6PrivacyExtensions,
"Failed to parse IPv6 privacy extensions option");
static const char* const ip_reverse_path_filter_table[_IP_REVERSE_PATH_FILTER_MAX] = {
[IP_REVERSE_PATH_FILTER_NO] = "no",
[IP_REVERSE_PATH_FILTER_STRICT] = "strict",
[IP_REVERSE_PATH_FILTER_LOOSE] = "loose",
};
DEFINE_STRING_TABLE_LOOKUP(ip_reverse_path_filter, IPReversePathFilter);
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip_reverse_path_filter, ip_reverse_path_filter, IPReversePathFilter,
"Failed to parse IP reverse path filter option");

View file

@ -17,10 +17,22 @@ typedef enum IPv6PrivacyExtensions {
_IPV6_PRIVACY_EXTENSIONS_INVALID = -EINVAL,
} IPv6PrivacyExtensions;
typedef enum IPReversePathFilter {
IP_REVERSE_PATH_FILTER_NO,
IP_REVERSE_PATH_FILTER_STRICT,
IP_REVERSE_PATH_FILTER_LOOSE,
_IP_REVERSE_PATH_FILTER_MAX,
_IP_REVERSE_PATH_FILTER_INVALID = -EINVAL,
} IPReversePathFilter;
int link_set_sysctl(Link *link);
int link_set_ipv6_mtu(Link *link);
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
const char* ip_reverse_path_filter_to_string(IPReversePathFilter i) _const_;
IPReversePathFilter ip_reverse_path_filter_from_string(const char *s) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
CONFIG_PARSER_PROTOTYPE(config_parse_ip_reverse_path_filter);