User Tools

Site Tools


doc:appunti:net:ipv6_on_ppp

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
doc:appunti:net:ipv6_on_ppp [2024/07/05 12:13] – [IPv6 source address problem] niccolodoc:appunti:net:ipv6_on_ppp [2026/10/06 10:34] (current) – [Configuring Shorewall6] niccolo
Line 57: Line 57:
 </code> </code>
  
-This is the reason why the IPv6 global (public) address is propbably not eccepted on that interface. To change (temporary) the ''accept_ra'' option for the ppp0 interface you can use the command:+This is the reason why the IPv6 global (public) address is probably not eccepted on that interface. To change (temporary) the ''accept_ra'' option for the ppp0 interface you can use the command:
  
 <code> <code>
Line 73: Line 73:
 We need to hook a script to the **ppp0 up event** and configure the options there. Because we are using the Shorewall firewall it is possibile to set the required actions into the Shorewall configuration and simply restart the Shorewall service on the ppp0 interface up event. See below an example of a **/etc/ppp/ipv6-up.d/ipv6-addresses-up** script. We need to hook a script to the **ppp0 up event** and configure the options there. Because we are using the Shorewall firewall it is possibile to set the required actions into the Shorewall configuration and simply restart the Shorewall service on the ppp0 interface up event. See below an example of a **/etc/ppp/ipv6-up.d/ipv6-addresses-up** script.
  
 +==== Static vs dynamic address ====
 +
 +A very common scenario is that the Internet provider **assigns a /64 prefix to the PPP interface** and delegates an **additional prefix** to be used **for the local LAN**, generally a /56. The prefix assigned to the PPP interface is often not guaranteed to remain the same over time and should therefore be considered **dynamic**. If you have negotiated **static IPv6 addresses** with the provider, they are very likely part of this additional delegated prefix.
  
  
Line 106: Line 109:
 /usr/bin/systemctl restart wide-dhcpv6-client.service /usr/bin/systemctl restart wide-dhcpv6-client.service
 </code> </code>
 +
 +===== Manual configuration of the IPv6 prefix delegation =====
 +
 +If your ISP assigns to you a **Prefix Delegation** (an IPv6 subnet), but it does not offer the **DHCPv6 service**, you need to configure the address manually. In our case the WAN IPv6 address is automatically negotiated on the ppp0 interface, so we manually configure the LAN IPv6 address (the delegated prefix) on the internal interface **br0**.
 +
 +Just add the following section into **/etc/netword/interfaces** file:
 +
 +<file>
 +iface br0 inet6 static
 +        address 2a02:2427:513:1c03::1
 +        netmask 64
 +</file>
 +
  
 ===== DHCPv6 client: the wide-dhcpv6-client.service ===== ===== DHCPv6 client: the wide-dhcpv6-client.service =====
Line 487: Line 503:
 </file> </file>
  
-Like for the IPv4, the **CLAMPMSS=Yes** is often required in **/etc/shorewall/shorewall.conf** (see above):+If you want to forward packets from internal interface to the external one (and vice-versa), you need to enable IP forwarding in **/etc/shorewall6/shorewall6.conf**: 
 + 
 +<file> 
 +IP_FORWARDING=On 
 +</file> 
 + 
 +Like for the IPv4, the **CLAMPMSS=Yes** is often required in **/etc/shorewall6/shorewall6.conf** (see above):
  
 <file> <file>
Line 547: Line 569:
 To give a **persistent addresses** to the client, take note of the DUID received by the server and put it into a **host** section of the server configuration **dhcp6s.conf** (see above). The DUID is composed of a 64 bit random string and the MAC address of the client's network interface; once generated, it is stored into a file named **/var/lib/dhcpv6/dhcp6c_duid**. To give a **persistent addresses** to the client, take note of the DUID received by the server and put it into a **host** section of the server configuration **dhcp6s.conf** (see above). The DUID is composed of a 64 bit random string and the MAC address of the client's network interface; once generated, it is stored into a file named **/var/lib/dhcpv6/dhcp6c_duid**.
  
-==== IPv6 source address problem ====+FIXME: What to do to protect LAN hosts from the internet?
  
-Enabling the DHCPv6 address only (i.e. disabling SLAAC configuration on the client) the IPv6 routing doese not work; we get the //Beyond scope of source address// error message. Sniffing the traffic on the default gateway we can see:+===== Using a static IPv6 address ===== 
 + 
 +You may need a **static IPv6 address** on your firewall for both incoming and outgoing connections: 
 + 
 +  * **Incoming connections:** to allow hosts on the Internet to reach the firewall at a known IPv6 address. 
 +  * **Outgoing connections:** to use a static IPv6 source address when accessing services on the Internet, allowing the remote server to filter incoming connections based on that address. 
 + 
 +As stated above, the address autoamtically assigned to the **ppp0** interface may be **dynamic**, so we must use one of the addresses from the **delegated /56 prefix**. 
 + 
 +In the configuration file **/etc/wide-dhcpv6/dhcp6c.conf** shown above we already defined the site-level aggregator ID 3 (**sla-id**) to be appended to the /56 prefix and the interface ID 1 (**ifid**) to obtain the full IPv6 address **2a02:2427:513:1c03::1** that is assigned to the **br0** interface. 
 + 
 +That IPv6 address is guaranteed to be static and assigned to the firewall, so you can use it for incoming connections and you can register it as an AAAA record in the DNS. But outgoiung IPv6 connections originating from the firewall itself use the ppp0 address, which may be dynamic. 
 + 
 +Therefore, we need a script that **sets the source IPv6 address** to the static address assigned to the **br0** interface, rather than the one dynamically assigned to the **ppp0** interface. This setting must be applied every time the ppp0 interface is activated, but only after the subnet delegation negotiation has completed. 
 + 
 +Here is the sample script  **/etc/wide-dhcpv6/dhcp6c-src-route**: 
 + 
 +<code bash> 
 +#!/bin/sh 
 +# /etc/wide-dhcpv6/dhcp6c-src-route   (chmod 755) 
 + 
 +# Execute first the default Debian script (DNS, etc.), if it exists. 
 +# We do not need this because the DNS is configured locally, not via DHCPv6. 
 +#[ -x /etc/wide-dhcpv6/dhcp6c-script ] && /etc/wide-dhcpv6/dhcp6c-script 
 + 
 +get_src() { 
 +    # Global address of br0, excluding those in DAD or deprecated. 
 +    ip -6 addr show dev br0 scope global -tentative -deprecated \ 
 +        | awk '/inet6/ {sub("/.*","",$2); print $2; exit}' 
 +} 
 + 
 +# It waits up to ~5 s for DAD to complete (a "tentative" address is 
 +# not accepted as the source address, and the command would fail). 
 +i=0 
 +SRC=$(get_src) 
 +while [ -z "$SRC" ] && [ $i -lt 10 ]; do 
 +    sleep 0.5 
 +    i=$((i+1)) 
 +    SRC=$(get_src) 
 +done 
 + 
 +[ -n "$SRC" ] || { logger -t dhcp6c-src "No valid IPv6 address on br0"; exit 0; } 
 + 
 +# Replaces (or adds, if it does not already exist) the default route with a metric of 100. 
 +ip -6 route replace default dev ppp0 metric 100 src "$SRC" \ 
 +    && logger -t dhcp6c-src "Default route via ppp0 with src $SRC" 
 +exit 0 
 +</code> 
 + 
 +To hook this script to the moment the IPv6 configuration is received, modify the **/etc/wide-dhcpv6/dhcp6c.conf** configuration file by replacing the default value of //script// in the //interface ppp0// section: 
 + 
 +<file> 
 +interface ppp0 { 
 +    # Send an option for "Identity Association for Prefix Delegation" with ID=0. 
 +    send ia-pd 0; 
 +    # Script executed when the daemon receives a reply message. 
 +    script "/etc/wide-dhcpv6/dhcp6c-src-route"; 
 +}; 
 +</file> 
 + 
 +If you need to call the default Debian hook script **/etc/wide-dhcpv6/dhcp6c-script** (used mainly to set the DNS nameserver on DHCPv6) you need to uncomment the relevant line in the scrtip above. 
 + 
 +You can see all the times that the script is executed (because the DHCPv6 lease renews) using the command:
  
 <code> <code>
-IP6 fe80::225:22ff:fedd:4598 > 2a01:4f8:1c17:7636::1: ICMP6, echo request, +journalctl --boot -t dhcp6c-src
-    id 56698, seq 1, length 64 +
-IP6 fe80::d003:a6ff:fef2:6fe8 > fe80::225:22ff:fedd:4598: ICMP6, destination unreachable, +
-    beyond scope 2a01:4f8:1c17:7636::1, source address fe80::225:22ff:fedd:4598, length 112+
 </code> </code>
  
-The default gateway on the client seems OK (check it with ''ip -6 route show''), but the source address is set to the **link scope** address instead of the **global** one. You can confirm it with the command ''ip -6 route get <ipv6_address>'':+===== Useful commands ===== 
 + 
 +Mostra la **rotta predefinita** per IPv6:
  
 <code> <code>
-ip -6 route get 2a01:4f8:1c17:7636::1 +ip -6 route show default 
-2a01:4f8:1c17:7636::1 from :: +</code> 
-    via 2a02:2420:503:1c03::1 +<code> 
-    dev enp0s7 +default dev ppp0 metric 1024 pref medium 
-    src fe80::225:22ff:fedd:4598 +default via fe80::be26:c7ff:fe0d:8bc0 dev ppp0 proto ra metric 1024 expires 1775sec hoplimit 64 pref medium
-    metric 1024 pref medium+
 </code> </code>
  
-You can compare the result when the SLAAC is enabled:+La prima riga indica una rotta predefinita verso l'interfaccia ppp0 senza specificare un gateway (non serve per una interfaccia punto-punto). È stata creata insieme all'interfaccia ppp0 grazie al parametro ''defaultroute6'' di pppd. Non scade. 
 + 
 +La seconda riga viene istanziata durante la negoziazione del Router Advertisement (abbiamo ''accept_ra = 2'' su ppp0), è stata impostata sull'indirizzo IPv6 del gateway e viene rinegoziata periodicamente. Se la rinegoziazione dovesse fallire, la rotta sparisce. 
 + 
 +Visualizza l'**indirizzo IPv6 globale** per l'interfaccia br0:
  
 <code> <code>
-ip -6 route get 2a01:4f8:1c17:7636::1 +ip -6 addr show dev br0 scope global 
-2a01:4f8:1c17:7636::1 from :: +</code> 
-    via fe80::d003:a6ff:fef2:6fe8 +<code> 
-    dev enp0s7 proto ra +5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 
-    src 2a02:2420:503:1c03:225:22ff:fedd:4598 +    inet6 2a02:2420:503:1c03::1/64 scope global  
-    metric 1024 hoplimit 64 pref medium+       valid_lft forever preferred_lft forever
 </code> </code>
  
-In the first case the **src** address is the **link scope** one, sot suitable for routing. In the second case it is the one received via SLAAC, which has a **global scope** and indeed it is working.+**Imposta o rimuove manualmente** un indirizzo IPv6 su una interfaccia:
  
-FIXME How to solve?+<code> 
 +ip -6 addr add 2a02:1640:cd04:3::1/64 dev eth1 
 +ip -6 addr del 2a02:1640:cd00:41df::1/64 dev eth1 
 +</code>
  
-FIXME: What to do to protect LAN hosts from the internet?+Mostra la **rotta selezionata** e **indirizzo sorgente** per un indirizzo IPv6 remoto: 
 + 
 +<code> 
 +ip -6 route get 2a01:4f8:1c17:7636::1 
 +</code> 
 +<code> 
 +2a01:4f8:1c17:7636::1 from :: dev ppp0 src 2a02:2420:105:61::1 metric 1024 pref medium 
 +</code> 
 + 
 +**Imposta la rotta predefinita** IPv6 indicando l'indirizzo origine e una metrica bassa (il valore 100 viene preferito a quello delle rotte predefinite 1024): 
 + 
 +<code> 
 +ip -6 route add default dev ppp0 metric 100 src 2a02:2420:503:1c03::1 
 +</code> 
 +<code> 
 +2a01:4f8:1c17:7636::1 from :: dev ppp0 src 2a02:2420:105:61::1 metric 1024 pref medium 
 +</code>
  
 ===== MRU and MTU for PPPoE ===== ===== MRU and MTU for PPPoE =====
Line 612: Line 717:
 ^ FF02::2            | All-routers multicast address.  | ^ FF02::2            | All-routers multicast address.  |
 ^ FF02::1:FFxx:xxxx  | Duplicate Address Detection multicast group.  | ^ FF02::1:FFxx:xxxx  | Duplicate Address Detection multicast group.  |
 +
 +
 +===== Troubleshooting IPv6 problems =====
 +
 +In general, to troubleshoot any networking issue, you use the **ping** command to check if the remote address is responding:
 +
 +<code>
 +# ping -6 2a01:4f8:1c17:7636::1
 +</code>
 +
 +In some cases it is useful also to **ping your own addresses** (you can have more than one). Discover all of them with:
 +
 +<code>
 +# ip -6 address show dev enp0s7
 +</code>
 +
 +<code>
 +2: enp0s7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
 +    inet6 2a02:2420:503:1c03::2/128 scope global dadfailed tentative 
 +       valid_lft forever preferred_lft forever
 +    inet6 2a02:2420:503:1c03:225:22ff:fedd:4598/64 scope global dynamic mngtmpaddr 
 +       valid_lft 86391sec preferred_lft 14391sec
 +    inet6 fe80::225:22ff:fedd:4598/64 scope link 
 +       valid_lft forever preferred_lft forever
 +</code>
 +
 +In the example above the interface have two **global** scope addresses, one assigned via DHCPv6 and the other obtained via SLAAC. The first one has the **dadfailed** flag, which means that the **duplicate address detection** has detected a conflict in the network. This means that the IP address in question will not be used as the source address and it does not even respond to a self-ping.
 +
 +If you have only one global IP address which is **dadfailed**, you cannot reach remote hosts on IPv6. It may be a difficult situation to diagnose, because using the simple **ifconfig** command you see the assigned IPv6 address and the **default route** is OK:
 +
 +<code>
 +# ip -6 route show
 +2a02:2420:503:1c03::2 dev enp0s7 proto kernel metric 256 pref medium
 +2a02:2420:503:1c03::/64 dev enp0s7 proto kernel metric 256 expires 86387sec pref medium
 +fe80::/64 dev enp0s7 proto kernel metric 256 pref medium
 +default via fe80::d003:a6ff:fef2:6fe8 dev enp0s7 proto ra metric 1024 expires 167sec hoplimit 64 pref medium
 +</code>
 +
 +**NOTICE**: The default router can be reached via its **link** scope address (as seen above) or via its **global** scope address: both can be used.
 +
 +If you sniff the ping request on the router, you can see the problem more clearly:
 +
 +<code>
 +# tcpdump -i eth0 -n 'icmp6'
 +...
 +IP6 fe80::225:22ff:fedd:4598 > 2a01:4f8:1c17:7636::1: ICMP6, echo request,
 +    id 56698, seq 1, length 64
 +IP6 fe80::d003:a6ff:fef2:6fe8 > fe80::225:22ff:fedd:4598: ICMP6, destination unreachable,
 +    beyond scope 2a01:4f8:1c17:7636::1, source address fe80::225:22ff:fedd:4598, length 112
 +</code>
 +
 +The client uses its link scope address as source address, which causes the **beyond scope** error. You can confirm this problem on the client using the ''ip route get'' command:
 +
 +
 +<code>
 +# ip -6 route get 2a01:4f8:1c17:7636::1
 +2a01:4f8:1c17:7636::1 from ::
 +    via 2a02:2420:503:1c03::1
 +    dev enp0s7
 +    src fe80::225:22ff:fedd:4598
 +    metric 1024 pref medium
 +</code>
 +
 +You can compare the result when you have at least one working global IP address:
 +
 +<code>
 +# ip -6 route get 2a01:4f8:1c17:7636::1
 +2a01:4f8:1c17:7636::1 from ::
 +    via fe80::d003:a6ff:fef2:6fe8
 +    dev enp0s7 proto ra
 +    src 2a02:2420:503:1c03:225:22ff:fedd:4598
 +    metric 1024 hoplimit 64 pref medium
 +</code>
 +
 +In the first case the **src** address is the **link scope** one, not suitable for routing. In the second case it is the one received via SLAAC, which has a **global scope** and indeed it is working. Notice that the address of the router (shown as the **via** address) is not releveant, even the //link scope// one does work.
 +
  
 ===== Web References ===== ===== Web References =====
doc/appunti/net/ipv6_on_ppp.1720174391.txt.gz · Last modified: by niccolo