Networking: Difference between revisions
imported>Hypnosis2839 →VLAN's: rename section, also usePredictableInterfaceNames was meant for backwards compat |
IPv6-mostly |
||
(10 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
This | Networking config always goes in your system configuration. This can be done declaratively as shown in the following sections or through non-declarative tools such as [[NetworkManager]]. | ||
== Configuration == | == Configuration == | ||
Line 5: | Line 5: | ||
=== Static IP for network adapter === | === Static IP for network adapter === | ||
The following example configures a static IPv6 address and a default gateway for the interface <code>ens3</code> | The following example configures a static IPv4 and IPv6 address and a default gateway for the interface <code>ens3</code> | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
networking = { | networking = { | ||
interfaces = { | interfaces.ens3 = { | ||
ipv6.addresses = [{ | |||
address = "2a01:4f8:1c1b:16d0::"; | address = "2a01:4f8:1c1b:16d0::1"; | ||
prefixLength = 64; | prefixLength = 64; | ||
}]; | }]; | ||
ipv4.addresses = [{ | |||
address = "192.0.2.2"; | |||
prefixLength = 24; | |||
}]; | |||
}; | |||
defaultGateway = { | |||
address = "192.0.2.1"; | |||
interface = "ens3"; | |||
}; | }; | ||
defaultGateway6 = { | defaultGateway6 = { | ||
Line 26: | Line 34: | ||
To edit <code>/etc/hosts</code> just add something like this to your <code>configuration.nix</code>: | To edit <code>/etc/hosts</code> just add something like this to your <code>configuration.nix</code>: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
networking. | networking.hosts = { | ||
127.0.0.2 other-localhost | "127.0.0.2" = ["other-localhost"]; | ||
"192.0.2.1" = ["mail.example.com" "imap.example.com"]; | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Port forwarding === | === Port forwarding === | ||
In this example we're going to forward the port <code>80</code> via NAT from our | In this example we're going to forward the port <code>80</code> via NAT from our internal network interface <code>ens3</code> to the host <code>10.100.0.3</code> on our external interface <code>wg0</code>. | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
networking = { | networking = { | ||
nftables = { | |||
enable = true; | |||
ruleset = '' | |||
table ip nat { | |||
chain PREROUTING { | |||
type nat hook prerouting priority dstnat; policy accept; | |||
iifname "ens3" tcp dport 80 dnat to 10.100.0.3:80 | |||
} | |||
} | |||
''; | |||
}; | |||
firewall = { | firewall = { | ||
enable = true; | enable = true; | ||
allowedTCPPorts = [ 80 ]; | allowedTCPPorts = [ 80 ]; | ||
}; | }; | ||
nat = { | nat = { | ||
enable = true; | enable = true; | ||
internalInterfaces = [ " | internalInterfaces = [ "ens3" ]; | ||
externalInterface = " | externalInterface = "wg0"; | ||
forwardPorts = [ | forwardPorts = [ | ||
{ | { | ||
Line 52: | Line 70: | ||
proto = "tcp"; | proto = "tcp"; | ||
destination = "10.100.0.3:80"; | destination = "10.100.0.3:80"; | ||
} | |||
]; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
For IPv6 port forwarding, the example would look like this. Incoming connections on the address <code>2001:db8::</code> and port <code>80</code> will be forwarded to <code>[fe80::1234:5678:9abc:def0]:80</code>. | |||
<syntaxhighlight lang="nix"> | |||
networking = { | |||
nftables = { | |||
enable = true; | |||
ruleset = '' | |||
table ip6 nat { | |||
chain PREROUTING { | |||
type nat hook prerouting priority dstnat; policy accept; | |||
iifname "ens3" ip6 daddr [2001:db8::] tcp dport 80 dnat to [fe80::1234:5678:9abc:def0]:80 | |||
} | |||
} | |||
''; | |||
}; | |||
firewall = { | |||
enable = true; | |||
allowedTCPPorts = [ 80 ]; | |||
}; | |||
nat = { | |||
enable = true; | |||
internalInterfaces = [ "ens3" ]; | |||
externalInterface = "wg0"; | |||
enableIPv6 = true; | |||
internalIPv6s = [ "2001:db8::/64" ]; | |||
externalIPv6 = "fe80::1234:5678:9abc:def0"; | |||
forwardPorts = [ | |||
{ | |||
sourcePort = 80; | |||
proto = "tcp"; | |||
destination = "fe80::1234:5678:9abc:def0]:80"; | |||
} | } | ||
]; | ]; | ||
Line 62: | Line 117: | ||
== Prefix delegation with fixed DUID == | == Prefix delegation with fixed DUID == | ||
Sometimes the hosting provider manages | Sometimes the hosting provider manages IPv6 networks via a so-called ''DUID'' or ''clientid''. This snippet is required to make the network routable: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 100: | Line 155: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== VLANs | == IPv6-mostly == | ||
For IPv6 mostly networks the situation in Linux is a little bit dire. | |||
A 464XLAT CLAT implementation on the client device has to be running. | |||
For example run clatd: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
services.clatd.enable = true; | |||
} | |||
</syntaxhighlight> | |||
Caveats: | |||
* disable IPv4 manually for DHCPv4 clients that do not accept Option 108 (IPv6-Only Preferred Option) | |||
* set NAT64 prefix manually, if client doesn't support RA/PREF64 (RFC 8781) or DNS64 (RFC 7050): | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
services.clatd.settings = { | |||
plat-prefix = "64:ff9b::/96"; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
* clatd needs to be restarted, if the network has changed | |||
Sources: | |||
* https://labs.ripe.net/author/ondrej_caletka_1/deploying-ipv6-mostly-access-networks/ | |||
* https://ripe85.ripe.net/presentations/9-RIPE85-Deploying_IPv6_mostly.pdf | |||
* https://github.com/systemd/systemd/issues/23674 | |||
* https://github.com/toreanderson/clatd | |||
* https://gist.github.com/oskar456/d898bf2e11b642757800a5ccdc2415aa | |||
* https://fosdem.org/2024/schedule/event/fosdem-2024-1798-improving-ipv6-only-experience-on-linux/ | |||
* https://nlnet.nl/project/IPv6-monostack/ | |||
= VLANs = | |||
Refer to [https://nixos.org/manual/nixos/stable/options.html#opt-networking.vlans {{ic|networking.vlans}} in the manual]. | Refer to [https://nixos.org/manual/nixos/stable/options.html#opt-networking.vlans {{ic|networking.vlans}} in the manual]. | ||
Line 108: | Line 196: | ||
{{ic|enp2s1}} is a normal network interface at {{ic|192.168.1.2}} with no VLAN information. | {{ic|enp2s1}} is a normal network interface at {{ic|192.168.1.2}} with no VLAN information. | ||
{{ic|enp2s0}} is the virtual LAN trunk | {{ic|enp2s0}} is the virtual LAN trunk with two tagged VLANs, {{ic|vlan100}} and {{ic|vlan101}}. | ||
{{ic|vlan100}} is in the {{ic|10.1.1.X}} network and {{ic|vlan101}} is in the {{ic|10.10.10.X}} network. | {{ic|vlan100}} is in the {{ic|10.1.1.X}} network and {{ic|vlan101}} is in the {{ic|10.10.10.X}} network. | ||
Line 142: | Line 230: | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Category:Networking]] |
Latest revision as of 08:30, 22 May 2024
Networking config always goes in your system configuration. This can be done declaratively as shown in the following sections or through non-declarative tools such as NetworkManager.
Configuration
Static IP for network adapter
The following example configures a static IPv4 and IPv6 address and a default gateway for the interface ens3
networking = {
interfaces.ens3 = {
ipv6.addresses = [{
address = "2a01:4f8:1c1b:16d0::1";
prefixLength = 64;
}];
ipv4.addresses = [{
address = "192.0.2.2";
prefixLength = 24;
}];
};
defaultGateway = {
address = "192.0.2.1";
interface = "ens3";
};
defaultGateway6 = {
address = "fe80::1";
interface = "ens3";
};
};
Hosts file
To edit /etc/hosts
just add something like this to your configuration.nix
:
networking.hosts = {
"127.0.0.2" = ["other-localhost"];
"192.0.2.1" = ["mail.example.com" "imap.example.com"];
};
Port forwarding
In this example we're going to forward the port 80
via NAT from our internal network interface ens3
to the host 10.100.0.3
on our external interface wg0
.
networking = {
nftables = {
enable = true;
ruleset = ''
table ip nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
iifname "ens3" tcp dport 80 dnat to 10.100.0.3:80
}
}
'';
};
firewall = {
enable = true;
allowedTCPPorts = [ 80 ];
};
nat = {
enable = true;
internalInterfaces = [ "ens3" ];
externalInterface = "wg0";
forwardPorts = [
{
sourcePort = 80;
proto = "tcp";
destination = "10.100.0.3:80";
}
];
};
};
For IPv6 port forwarding, the example would look like this. Incoming connections on the address 2001:db8::
and port 80
will be forwarded to [fe80::1234:5678:9abc:def0]:80
.
networking = {
nftables = {
enable = true;
ruleset = ''
table ip6 nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
iifname "ens3" ip6 daddr [2001:db8::] tcp dport 80 dnat to [fe80::1234:5678:9abc:def0]:80
}
}
'';
};
firewall = {
enable = true;
allowedTCPPorts = [ 80 ];
};
nat = {
enable = true;
internalInterfaces = [ "ens3" ];
externalInterface = "wg0";
enableIPv6 = true;
internalIPv6s = [ "2001:db8::/64" ];
externalIPv6 = "fe80::1234:5678:9abc:def0";
forwardPorts = [
{
sourcePort = 80;
proto = "tcp";
destination = "fe80::1234:5678:9abc:def0]:80";
}
];
};
};
IPv6
Prefix delegation with fixed DUID
Sometimes the hosting provider manages IPv6 networks via a so-called DUID or clientid. This snippet is required to make the network routable:
{ config, pkgs, ... }:
let
# Get this from your hosting provider
clientid = "00:11:22:33:44:55:66:77:88:99";
interface = "enp2s0";
subnet = "56";
network = "2001:bbb:3333:1111::/${subnet}";
own_ip = "2001:bbb:3333:1111::1/${subnet}";
in {
# ... snip ...
networking.enableIPv6 = true;
networking.useDHCP = true;
networking.dhcpcd.persistent = true;
networking.dhcpcd.extraConfig = ''
clientid "${clientid}"
noipv6rs
interface ${interface}
ia_pd 1/${network} ${interface}
static ip6_address=${own_ip}
'';
environment.etc."dhcpcd.duid".text = clientid;
}
Source: gleber gist for online.net IPv6 config in NixOS
Note: Recent versions of dhcpcd move the duid file to /var/db/dcpcd/duid. For that to work, you have to replace the above environment.etc line with something like:
systemd.services.dhcpcd.preStart = ''
cp ${pkgs.writeText "duid" "<ID>"} /var/db/dhcpcd/duid
'';
IPv6-mostly
For IPv6 mostly networks the situation in Linux is a little bit dire. A 464XLAT CLAT implementation on the client device has to be running.
For example run clatd:
{
services.clatd.enable = true;
}
Caveats:
- disable IPv4 manually for DHCPv4 clients that do not accept Option 108 (IPv6-Only Preferred Option)
- set NAT64 prefix manually, if client doesn't support RA/PREF64 (RFC 8781) or DNS64 (RFC 7050):
{
services.clatd.settings = {
plat-prefix = "64:ff9b::/96";
};
}
- clatd needs to be restarted, if the network has changed
Sources:
- https://labs.ripe.net/author/ondrej_caletka_1/deploying-ipv6-mostly-access-networks/
- https://ripe85.ripe.net/presentations/9-RIPE85-Deploying_IPv6_mostly.pdf
- https://github.com/systemd/systemd/issues/23674
- https://github.com/toreanderson/clatd
- https://gist.github.com/oskar456/d898bf2e11b642757800a5ccdc2415aa
- https://fosdem.org/2024/schedule/event/fosdem-2024-1798-improving-ipv6-only-experience-on-linux/
- https://nlnet.nl/project/IPv6-monostack/
VLANs
Refer to networking.vlans
in the manual.
Below is a complete networking example showing two interfaces, one with VLAN trunk tagging and one without.
enp2s1
is a normal network interface at 192.168.1.2
with no VLAN information.
enp2s0
is the virtual LAN trunk with two tagged VLANs, vlan100
and vlan101
.
vlan100
is in the 10.1.1.X
network and vlan101
is in the 10.10.10.X
network.
The hostID
should be unique among your machines, as mentioned in the manual.
Complete networking section example:
networking = {
hostId = "deadb33f";
hostName = "nixos";
domain = "example.com";
dhcpcd.enable = false;
interfaces.enp2s1.ipv4.addresses = [{
address = "192.168.1.2";
prefixLength = 28;
}];
vlans = {
vlan100 = { id=100; interface="enp2s0"; };
vlan101 = { id=101; interface="enp2s0"; };
};
interfaces.vlan100.ipv4.addresses = [{
address = "10.1.1.2";
prefixLength = 24;
}];
interfaces.vlan101.ipv4.addresses = [{
address = "10.10.10.3";
prefixLength = 24;
}];
defaultGateway = "192.168.1.1";
nameservers = [ "1.1.1.1" "8.8.8.8" ];
};