From 1659d75265bb5a0d22058fcbd87a6e42c2b11270 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 13 Dec 2020 21:57:45 +0100 Subject: [PATCH 01/41] Add FritzBox guide Signed-off-by: yubiuser --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 54da3ef0..7f848fb6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -98,6 +98,7 @@ nav: - 'Configuring NGINX for Pi-hole': guides/nginx-configuration.md - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md + - 'Configuring Fritzboxes for Pi-hole': guides/fritzbox.md - 'Benchmarking': guides/benchmark.md - 'Pi-hole and OpenVPN Server': - 'Overview': guides/vpn/overview.md From a539fc9f24a7b28240722f17e7fcb175076f6eb9 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 13 Dec 2020 22:03:29 +0100 Subject: [PATCH 02/41] Add guide file Signed-off-by: yubiuser --- docs/guides/fritzbox.md | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/guides/fritzbox.md diff --git a/docs/guides/fritzbox.md b/docs/guides/fritzbox.md new file mode 100644 index 00000000..1c3a7217 --- /dev/null +++ b/docs/guides/fritzbox.md @@ -0,0 +1,69 @@ +**This is an unsupported configuration created by the community** + +This guide was developed using a FritzBox 7530 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritzboxes . + +> Note: +There is no single way to do it right. Choose the one best fitting your needs. +This guide is IPv4 only. You need to adjust for IPv6 accordingly + +## 1) Using Pihole as upstream DNS server for your Fritzbox + +Using this configuration, Pihole is used for all devices within your network including the FritzBox itself. DNS requests are send in this order + +```bash +Client -> FritzBox -> Pihole -> Upstream DNS Server +``` + +To set it up, enter Pihole's IP as "Bevorzugter DNS-Server" **and** "Alternativer DNS-Server" in + +```bash +Internet/Zugangsdaten/DNS-Server +``` + +!!! warning + Don't set the FitzBox as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritzbox which in turn will send the to Pihole. + +With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your FitzBox. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. + + +## 2) Distribute Pihole as DNS server via DHCP + +Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your FritzBox. +DNS requests are send in this order + +```bash +Client -> Pihole -> Upstream DNS Server +``` + +> Note: +The FritzBox itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. +The FritzBox can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritzbox. This would cause a DNS loop. + +To set it up, enter Pihole's IP as "Lokaler DNS-Server" in + +```bash +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +``` + +You should see individual clients in Pihole's web dashboard. + +## 3) Combining 1) and 2) + +You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritzbox itself as well. + +```bash +Client (incl. FritzBox) -> Pihole -> Upstream DNS Server +``` + +!!! warning + Don't set the FitzBox as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritzbox which in turn will send the to Pihole + +## Using Pihole within the Guest Network + +You may have noticed, that there is no option to set the DNS server for the guest network in + +```bash +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +``` + +The FritzBox always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your FitzBox (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your FritzBox. From 15862ba397c4e6a6e2b80ccda26ae5556194d535 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 13 Dec 2020 22:07:29 +0100 Subject: [PATCH 03/41] Fix trailing spaces Signed-off-by: yubiuser --- docs/guides/fritzbox.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guides/fritzbox.md b/docs/guides/fritzbox.md index 1c3a7217..1ff4a5ef 100644 --- a/docs/guides/fritzbox.md +++ b/docs/guides/fritzbox.md @@ -2,7 +2,7 @@ This guide was developed using a FritzBox 7530 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritzboxes . -> Note: +> Note: There is no single way to do it right. Choose the one best fitting your needs. This guide is IPv4 only. You need to adjust for IPv6 accordingly @@ -28,14 +28,14 @@ With this configuration, you won't see individual clients in pihole's dashboard. ## 2) Distribute Pihole as DNS server via DHCP -Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your FritzBox. +Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your FritzBox. DNS requests are send in this order ```bash Client -> Pihole -> Upstream DNS Server ``` -> Note: +> Note: The FritzBox itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. The FritzBox can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritzbox. This would cause a DNS loop. From 584bb146b3241734734acb9abc43ff80ae5b5a75 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 20:30:07 +0100 Subject: [PATCH 04/41] Fix name according to vendor Signed-off-by: yubiuser --- docs/guides/fritzbox.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/guides/fritzbox.md b/docs/guides/fritzbox.md index 1ff4a5ef..0271350a 100644 --- a/docs/guides/fritzbox.md +++ b/docs/guides/fritzbox.md @@ -1,17 +1,17 @@ **This is an unsupported configuration created by the community** -This guide was developed using a FritzBox 7530 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritzboxes . +This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritz!Boxes . > Note: There is no single way to do it right. Choose the one best fitting your needs. This guide is IPv4 only. You need to adjust for IPv6 accordingly -## 1) Using Pihole as upstream DNS server for your Fritzbox +## 1) Using Pihole as upstream DNS server for your Fritz!Box -Using this configuration, Pihole is used for all devices within your network including the FritzBox itself. DNS requests are send in this order +Using this configuration, Pihole is used for all devices within your network including the Fritz!Box itself. DNS requests are send in this order ```bash -Client -> FritzBox -> Pihole -> Upstream DNS Server +Client -> Fritz!Box -> Pihole -> Upstream DNS Server ``` To set it up, enter Pihole's IP as "Bevorzugter DNS-Server" **and** "Alternativer DNS-Server" in @@ -21,14 +21,14 @@ Internet/Zugangsdaten/DNS-Server ``` !!! warning - Don't set the FitzBox as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritzbox which in turn will send the to Pihole. + Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. -With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your FitzBox. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. +With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your Fritz!Box. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. ## 2) Distribute Pihole as DNS server via DHCP -Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your FritzBox. +Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. DNS requests are send in this order ```bash @@ -36,8 +36,8 @@ Client -> Pihole -> Upstream DNS Server ``` > Note: -The FritzBox itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. -The FritzBox can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritzbox. This would cause a DNS loop. +The Fritz!Box itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. +The Fritz!Box can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritz!Box. This would cause a DNS loop. To set it up, enter Pihole's IP as "Lokaler DNS-Server" in @@ -45,18 +45,21 @@ To set it up, enter Pihole's IP as "Lokaler DNS-Server" in Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration ``` +>Note: +Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. + You should see individual clients in Pihole's web dashboard. ## 3) Combining 1) and 2) -You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritzbox itself as well. +You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritz!Box itself as well. ```bash -Client (incl. FritzBox) -> Pihole -> Upstream DNS Server +Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server ``` !!! warning - Don't set the FitzBox as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritzbox which in turn will send the to Pihole + Don't set the Fritz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole ## Using Pihole within the Guest Network @@ -66,4 +69,4 @@ You may have noticed, that there is no option to set the DNS server for the gues Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration ``` -The FritzBox always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your FitzBox (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your FritzBox. +The Fritz!Box always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. From 972909e04425989c01b4ed6bc17828c3275ef9a6 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 20:37:47 +0100 Subject: [PATCH 05/41] Use English terminology Signed-off-by: yubiuser --- docs/guides/fritzbox.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/guides/fritzbox.md b/docs/guides/fritzbox.md index 0271350a..852654f1 100644 --- a/docs/guides/fritzbox.md +++ b/docs/guides/fritzbox.md @@ -14,10 +14,10 @@ Using this configuration, Pihole is used for all devices within your network inc Client -> Fritz!Box -> Pihole -> Upstream DNS Server ``` -To set it up, enter Pihole's IP as "Bevorzugter DNS-Server" **and** "Alternativer DNS-Server" in +To set it up, enter Pihole's IP as "Preferred DNS server" **and** "Alternative DNS server" in ```bash -Internet/Zugangsdaten/DNS-Server +Internet/Account Information/DNS server ``` !!! warning @@ -36,13 +36,13 @@ Client -> Pihole -> Upstream DNS Server ``` > Note: -The Fritz!Box itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. +The Fritz!Box itself will use whatever is configured in Internet/Account Information/DNS server. The Fritz!Box can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritz!Box. This would cause a DNS loop. -To set it up, enter Pihole's IP as "Lokaler DNS-Server" in +To set it up, enter Pihole's IP as "Local DNS server" in ```bash -Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Network ``` >Note: @@ -66,7 +66,7 @@ Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server You may have noticed, that there is no option to set the DNS server for the guest network in ```bash -Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Guest Network ``` The Fritz!Box always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. From 2d58aef2e84425435431b69da20a0756d3e243cf Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 20:44:51 +0100 Subject: [PATCH 06/41] Create 'Router setup' menu Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 72 ++++++++++++++++++++++++++++ docs/{guides => routers}/fritzbox.md | 0 2 files changed, 72 insertions(+) create mode 100644 docs/routers/fritzbox-de.md rename docs/{guides => routers}/fritzbox.md (100%) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md new file mode 100644 index 00000000..0271350a --- /dev/null +++ b/docs/routers/fritzbox-de.md @@ -0,0 +1,72 @@ +**This is an unsupported configuration created by the community** + +This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritz!Boxes . + +> Note: +There is no single way to do it right. Choose the one best fitting your needs. +This guide is IPv4 only. You need to adjust for IPv6 accordingly + +## 1) Using Pihole as upstream DNS server for your Fritz!Box + +Using this configuration, Pihole is used for all devices within your network including the Fritz!Box itself. DNS requests are send in this order + +```bash +Client -> Fritz!Box -> Pihole -> Upstream DNS Server +``` + +To set it up, enter Pihole's IP as "Bevorzugter DNS-Server" **and** "Alternativer DNS-Server" in + +```bash +Internet/Zugangsdaten/DNS-Server +``` + +!!! warning + Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. + +With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your Fritz!Box. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. + + +## 2) Distribute Pihole as DNS server via DHCP + +Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. +DNS requests are send in this order + +```bash +Client -> Pihole -> Upstream DNS Server +``` + +> Note: +The Fritz!Box itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. +The Fritz!Box can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritz!Box. This would cause a DNS loop. + +To set it up, enter Pihole's IP as "Lokaler DNS-Server" in + +```bash +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +``` + +>Note: +Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. + +You should see individual clients in Pihole's web dashboard. + +## 3) Combining 1) and 2) + +You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritz!Box itself as well. + +```bash +Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server +``` + +!!! warning + Don't set the Fritz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole + +## Using Pihole within the Guest Network + +You may have noticed, that there is no option to set the DNS server for the guest network in + +```bash +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +``` + +The Fritz!Box always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. diff --git a/docs/guides/fritzbox.md b/docs/routers/fritzbox.md similarity index 100% rename from docs/guides/fritzbox.md rename to docs/routers/fritzbox.md From 62e8ef2d7f9e0ef2bd8f120ca6cdab0e0512ec58 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 20:46:15 +0100 Subject: [PATCH 07/41] Update mkdocs.yml Signed-off-by: yubiuser --- mkdocs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 7f848fb6..31eaaed6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -98,7 +98,6 @@ nav: - 'Configuring NGINX for Pi-hole': guides/nginx-configuration.md - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md - - 'Configuring Fritzboxes for Pi-hole': guides/fritzbox.md - 'Benchmarking': guides/benchmark.md - 'Pi-hole and OpenVPN Server': - 'Overview': guides/vpn/overview.md @@ -119,6 +118,8 @@ nav: - 'Using TOR': guides/tor/using-tor.md - 'Performance and other issues': guides/tor/performance-issues.md - 'Using DNSSEC': guides/tor/dnssec.md + - 'Router setup': + - 'Fritz!Boxes (EN)': routers/fritzbox.md - 'Community Projects': main/projects.md extra: From ab670e79afa5b6de8b63ba35747ee8f9ea01d3c7 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 21:52:02 +0100 Subject: [PATCH 08/41] Add German translation Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 59 +++++++++++++++++++------------------ mkdocs.yml | 3 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index 0271350a..c2a1c08e 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -1,72 +1,75 @@ -**This is an unsupported configuration created by the community** +**Dies ist eine inoffizielle Anleitung die durch die Community gepflegt wird** -This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritz!Boxes . +Diese Anleitung wurde für FRITZ!OS 07.21 geschrieben, sollte jedoch auch mit anderen Firmware-Versionen funktionieren. Ziel ist es, grundlegende Prinzipien für ein reibungsloses Zusammenspiel zwischen Fritz!Box und Pihole zu verdeutlichen. -> Note: -There is no single way to do it right. Choose the one best fitting your needs. -This guide is IPv4 only. You need to adjust for IPv6 accordingly +> Hinweis: +Es gibt nicht nur **die eine Art**, eine funktionierende DNS System aufzusetzen. Konfiguriert euer Netzwerk nach euren Bedürfnissen. +Diese Anleitung wurde für IPv4 geschrieben und muss für IPv6 Netwerke entsprechend angepasst werden. -## 1) Using Pihole as upstream DNS server for your Fritz!Box +## 1) Pihole als Upstream DNS Server der Fritz!Box (WAN Seite) -Using this configuration, Pihole is used for all devices within your network including the Fritz!Box itself. DNS requests are send in this order +Mit dieser Konfiguration, wird Pihole für alle Geräte im Netzwerk, incl. der Fritz!Box genutzt. DNS Anfragen nehmen folgenden Weg ```bash Client -> Fritz!Box -> Pihole -> Upstream DNS Server ``` -To set it up, enter Pihole's IP as "Bevorzugter DNS-Server" **and** "Alternativer DNS-Server" in +Zum Einstellen muss die IP des Pihole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in ```bash Internet/Zugangsdaten/DNS-Server ``` +eingertagen werden. !!! warning - Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. + Die Fritz!Box darf nicht als upstream DNS Server im Pihole eingestellt werden. Dies würde zu einem DNS Loop führen, da Pihole dann die Anfragen an dieFritz!Box senden würde, welche sie wiederum an Pihole senden würde. -With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your Fritz!Box. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. +Mit dieser Konfiguration sind im Pihole Dashboard keine individuellen Clients sichtbar. Für Pihole scheinen alle Anfragen von der Fritz!Box zu kommen. Dadurch können nicht alle Funktionen von Pihole genutzt werden, z.B. die Möglichkeit, Clients individuell zu filtern (Group Management). Wenn dies gewünscht ist, muss die Konfiguration #2 verwendet werden. -## 2) Distribute Pihole as DNS server via DHCP +## 2) Pihole als DNS Server via DHCP an Clients verteilen (LAN Seite) -Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. -DNS requests are send in this order +Mit dieser Konfiguration wird allen Clients die IP des Pihole als DNS Server angeboten, wenn sie einen DHCP Lease vom der Fritz!Box anfordern. +DNS Anfragen nehmen folgenden Weg ```bash Client -> Pihole -> Upstream DNS Server ``` -> Note: -The Fritz!Box itself will use whatever is configured under Internet/Zugangsdaten/DNS-Server. -The Fritz!Box can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritz!Box. This would cause a DNS loop. +> Hinweis: +Die Fritz!Box selbst wird den unter Internet/Zugangsdaten/DNS-Server eingestellten DNS Server nutzen. +Die Fritz!Box kann der Upstream Server von Pihole sein, solange Pihole nicht der Upstream Server der Fritz!Box ist. Dies würde zu einem DNS Loop führen. -To set it up, enter Pihole's IP as "Lokaler DNS-Server" in +Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server" in ```bash -Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz ``` +eingetragen werden. ->Note: -Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. +>Hinweis: +Clients bemerken Änderungen an den DHCP Einstellungen erst, wenn der DHCP Lease erneuert wird. Der einfachste Weg dies zu erzwingen ist ein Unterbrechen und Wiederherstellen der Netzwerkverbindung. -You should see individual clients in Pihole's web dashboard. +Nun sollen einzelne Clients in Piholes Dashboard auftrauchen. -## 3) Combining 1) and 2) +## 3) Kombination aus 1) und 2) -You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritz!Box itself as well. +Durch die Kombination von 1) und 2) senden alle Clients und die Fritz!Box selbst DNS Anfragen direkt an Pihole. ```bash Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server ``` !!! warning - Don't set the Fritz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole + Die Fritz!Box darf nicht als Upstream DNS Server des Pihole gesetzt werden. Dies würde zu einem DNS Loop führen, da Pihole die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pihole weitergeben würde. -## Using Pihole within the Guest Network +## Pihole im Gastnetzwerk nutzen -You may have noticed, that there is no option to set the DNS server for the guest network in +Es gibt in der Fritz!Box keine Möglichkeit unter ```bash -Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration +Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Gastnetz ``` +den DNS Server des Gastnetzwerks einzustellen. -The Fritz!Box always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. +Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pihole zu senden, muss der als Upstream DNS für die Fritz!Box (siehe #1) eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pihole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. diff --git a/mkdocs.yml b/mkdocs.yml index 31eaaed6..f8d4adb4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -119,7 +119,8 @@ nav: - 'Performance and other issues': guides/tor/performance-issues.md - 'Using DNSSEC': guides/tor/dnssec.md - 'Router setup': - - 'Fritz!Boxes (EN)': routers/fritzbox.md + - 'Fritz!Box (EN)': routers/fritzbox.md + - 'Fritz!Box (DE)': routers/fritzbox-de.md - 'Community Projects': main/projects.md extra: From 485a047af87226457516a75ed00b311655f86bed Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 21:55:30 +0100 Subject: [PATCH 09/41] Fix markdownlint Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index c2a1c08e..218b637a 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -19,6 +19,7 @@ Zum Einstellen muss die IP des Pihole als "Bevorzugter DNS-Server" **und** "Alte ```bash Internet/Zugangsdaten/DNS-Server ``` + eingertagen werden. !!! warning @@ -45,6 +46,7 @@ Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz ``` + eingetragen werden. >Hinweis: @@ -70,6 +72,7 @@ Es gibt in der Fritz!Box keine Möglichkeit unter ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Gastnetz ``` + den DNS Server des Gastnetzwerks einzustellen. Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pihole zu senden, muss der als Upstream DNS für die Fritz!Box (siehe #1) eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pihole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. From a395743249498f12fa7983ce11e0e28de0daa51a Mon Sep 17 00:00:00 2001 From: yubiuser Date: Wed, 16 Dec 2020 22:07:28 +0100 Subject: [PATCH 10/41] Fix markdownlint2 Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index 218b637a..17750be3 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -50,7 +50,7 @@ Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz eingetragen werden. >Hinweis: -Clients bemerken Änderungen an den DHCP Einstellungen erst, wenn der DHCP Lease erneuert wird. Der einfachste Weg dies zu erzwingen ist ein Unterbrechen und Wiederherstellen der Netzwerkverbindung. +Clients bemerken Änderungen an den DHCP Einstellungen erst, wenn der DHCP Lease erneuert wird. Der einfachste Weg dies zu erzwingen ist ein Unterbrechen und Wiederherstellen der Netzwerkverbindung. Nun sollen einzelne Clients in Piholes Dashboard auftrauchen. From f717de8d2f1f45d052a52cbc54cfc8b590d5c2d5 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 17 Dec 2020 06:55:24 +0100 Subject: [PATCH 11/41] Add screenshots Signed-off-by: yubiuser --- docs/images/fritzbox-dhcp-de.png | Bin 0 -> 42135 bytes docs/images/fritzbox-dhcp.png | Bin 0 -> 41058 bytes docs/images/fritzbox-wan-dns-de.png | Bin 0 -> 28000 bytes docs/images/fritzbox-wan-dns.png | Bin 0 -> 27213 bytes docs/routers/fritzbox-de.md | 2 ++ docs/routers/fritzbox.md | 2 ++ 6 files changed, 4 insertions(+) create mode 100644 docs/images/fritzbox-dhcp-de.png create mode 100644 docs/images/fritzbox-dhcp.png create mode 100644 docs/images/fritzbox-wan-dns-de.png create mode 100644 docs/images/fritzbox-wan-dns.png diff --git a/docs/images/fritzbox-dhcp-de.png b/docs/images/fritzbox-dhcp-de.png new file mode 100644 index 0000000000000000000000000000000000000000..91a9600f1e7c445351af6ef1a6ef9b9b76c598b0 GIT binary patch literal 42135 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

l5l>Kmq! z^r|scY2z9O&X>Szc%rQ_e(e4*W7+z$Ju7&Wa*#v5=y#3TaF*zp&&68lshuv<1IC52 zG)Ir>xXa|sduC`0CimtVindj!gy5wavTkH9X$xPVYknDKq$fT_n3lgoKQ`@lkOLDW0x4Wb=_T@mqO#r3XBb8gI7rYqVU9 zjy%9#C>WDSP60Q4T$M;-?wHvH-GA~a;u}lOhvWq|xv5IaT*b{7$2R5<@ch53{HFO@Djca#cR&T274p#Fo7PC)&{0l zLn(G->Qp$h@@twk?PdEQ`=@@DIwa;ZA#t#QwO5?|t80!w@L!5Ta>Me+B~Av$>wEUM zbA{=tn&C#q%HJ{~v;-3wkDZChUhM>LaJs*rAni^j%_hhZ(_AXeQT)9Qb?b;2CUII3 z5b&#vnvaN*QyHGGbL7bt(fdhoTxKTAgzbW3;-l(X_mZ$QW>Sa%aAhN2Qe1TS%LV!N zsF3l*-*JUec{`5QP^cK{<=Gv*>jU?8mDU40Cqt ze2M)>D2IKYraAl9Nntp*sP9#F`fFjyrU6B+K@~W8x4@G5E+o<)OFK+PCMh%I&V~ZW zhy!<%-ir!21PF_DSir@o3t+*nYlCHu2?-n@jD4mCc3 zp!>GKn3NaJ#39@C;^!Z>*60CV{HmBO>xMm5JjLEkBlsD;kLtNw5jh}N?{Xs!asAH} zM(|HZlHgQ2c&)?Nez~-PmqQ)g5Ylr$cB|;x%P?h0LZ9i*!q+k2O+$z2M*59A#|tR< z7>!$Ed*RjrDmH#yoKvY5OZAVnO*l?M9df&wrD!Rq2`{zVIO@f5O4%0^>-#HJrw{>S zp=V zCXEZXT$nf_VQFnwNYEOp6gKsX|JHpzu_whyy(n?fxV56Ry$@ZeNcI$f8!jU^-fRso z5kb8?Sm=Q5O$zv98hYY1njM`GCoO?X#FqNn)7^*}@$0l(0d^&4W=kMuVWSGpq~VyZWl|NSnVovwB-ohKCO7Jr1=J zqxaiLNPJ^T8Hrn++C!V-oWs zLd-Iw&h!{d;PF=El8nl)xtb_3l>1f=cg15l+T7h8{pNUEwM{+#HVi8|8(sV+v7hlM zg$8J!)EHashs0~9A9y#F@$MaO8k5VNg~94py_}>f4Ti-X;Y$W<7{wD72{jP7K6kOo&A;zdKlM));vPOH7&rdK(`gL=h!7*(? zXz5Q{ZccQ1>PznbCW5+ZCS>23i@9zCtvsK}=BI)^7D##jmx-dF(h9(Bmo%;zynp>6 z#0Ed;V6@s;3(($C3uY3jsPXch$a2# zxV_PnIKnR|S1abGq;aOZc?4|>_)5vr!4Sws2XoYnepXJmT;4@VfSCCjRIewkS%(vd z1(?4~0?V|ntvGNVx=rjjHBYKsS`MGM1zuu66hA;-QrD0Tu4EfE{BdY*@?mcl?@d(u zjVxquD8D8Wsp>dYRni>JKRTTKYH_f)a+*mlcsl>pHNHf&T?M~oZ0RD7yVKcklJxe<8knqzLR^!}rOdFmQ6_Yj(hPqQ0p?qC zC3NTLeb<{ARP3V4C1!@xBb*|f72;mdz<5!)^Rx~kIqt1QG?*jJjO?Z4p{R=yHd4Pt z$EWL{{aNLIFTd%fcYoP+mKeKQvJ8g&8Stf@73GOpQ8_me+>RNU4Z1IoQ3m}!y6rou zC`}wZoR2xt+~9cJ!!gH&m(q2_AXC{(h5q3~`lsk%hLf%2ghhUOgyqIBNq@Ie?dfcJ zeCf7DYhA2}8;l^{P$8m=JJtK)(r%tI*-xvbCx0R&sZKYF{~1VO!oy@4W$_)Bu1MMyrC}~JtAfqJpLR~Y_R=eb>yS59lcV7S zuahkvi@nLWkYZ6(UH(trCB^0){;FJpyZGbJh_G(^7bTC))Z(?$b6FKj^AMXh4sAfo z{~AO&&X&NcZ7-_+Zj>Fg- z7WcjEoxzJ*@a3J&<_MPT&Ko*vrI0(kcwH$gYS$aBNhaMhv`;Lp;}oFi(i`D8xWM14 z{kw!!S_66+bxn(YMnuxFDfe2YRcx%8a(V*-Oajc4*3&3Kz=Z&ZOauc}l?s$PuIvfr z##%{1;%m)>pnFb7m0=I^Si1xy{ML|xy@W?1XM~t2WHwQR86xgSEl|)13xXdgr+|^2 zK~?dIz|)Ns(N;8A^fr8*1N4K#Q3ORE`RVSaj)7hQ0+xuz$a)(peakLM+6xXc z*sH!od&3$HC_}*Zs2frh-#!5){%}JP0i)PH+*p8w+A-~f)`oxU0FqEaQ^x`HWHJ-ahq^c`7Pza z3B@7}UZgqo8Uqqn``iM8U)qC9(E``ql~tNvH(*)wjHTxBh^-d1Pkw!3v3jdm##u7r zD0qqqxU6BbWN#4w${AnO5>j9vNH=1IK|j49KNmNgRjuBDgt{B8k@?Kq$5p>o6AWsk zMyjQhhFf61;vUpVd=galh$BO8f;$CB0=)g8z*n8Ja{mid?$&T1i~CiMLHq7xqv|mO zsr@6Sl9D$zDC5qzkqJ^f1vUJ>rOKoD!k^t_#e}lj~Mt+Ay`H+hICBAb3Q4#zTfANQD@463!A8Cxd+~$h7ShnMPHy*DJ#8(E&CKnLe)MeJ%zPeRTM1q}+@({) z#?{{+aYQbYdKxA=J@HXp!O#FyR-GCNkzfMy$KPp8tdQD2>Bnu3_wk}6C6naFTbd^_ zKx`|jW%!+1MWK28rhf1=QpjCmlKl~BA$f#16QD6+IP-GNJ=O)oeF9@pej!(~n{qUC zJ_)=}=Sh+f)qT4GMroBoEcnlTc$utt`FPk9UK#`;|9lkV9$OZB(WdmrZ+S)9yipC` zzE630-iw~ik=>O_F3SnJK(K_`Z@yke9lNbwB9dYU66nUvhYR6vnDIVEJ~Y3?S!+La z(XS45vY$u!G94K}^!fwrwKlm{#ZO6vVGpo2A}gZ|XJY^2IxG1mCl!p8j)c8EI+Fxm z4QCx1PmU4S(?r)+4?np*R2g^(P#VDI+5m!z5(e|ve@=c6V0J^ z!jz2!9r|yETBx{+*_Gghzki6P%bfeS?VT4{e*_PhQH~El2ya!0q}QD0l~55EiyC*7 z7-{eSiYZ`Hlo3&ttkEg3wigw$3Xg&MufL_O2J;R@EQ=dMN~zQy#-9Y z^1%&FQXW?!%B3xd1hREBX0IL~X`P;B?YCe%t*AAfZipN}oRlE*wPYBpFNaudhn2&& zmXBh^s)QVHzPIr3)jxJFTbz_%OxNH~OchHjiKyeR7FPpj@VI2iTq$yqkO+2RdYoEC zCT~?Y=S2-Gkkp-eI8?mFVCC2lA+FC7sN{IJBo=10qt*6C0WyEgfG9fju`O>9$Sq!y zfEZ3_E)g&?oplRPkqXx5lInMOi*0@0$ehup3hi2|1dqqzeA#%?C!0War|Lmy6FPuF zT)!y#;%O^br}YsNazN+Zl>@H5mj-0sguNsugIk~d=lS?xVhx8f54bct%+q}qB7{II zsb>{<|EHXU^D7~UFAGiJB|Qd!bii!bo(QFmze9s&c^bcN-A5!FQJ^p_Fl2$%i#hCA zJDU$+B@zUe052FhL)@ASg}Hs!eWiPdMwb;?;2t}GRyzMoRjtC~>jvn&$E7VY5}MyG z8b?-~GxLUb!`D3Ih&BusY`jfn#(4QsYJiAPVR#WEY!o8hg82Xq^J<}Bh?*v=!&Jh_ zB|Z^96ir%#I#&<|1SG?LIHGU#q-rrP`z;?ea=txV4b({pOtYD$d=jR4=WdeT1m}(B zbDxwodV&$OMjH-x(tq@-MYk=qQw}o!!8$(nm(#iQCu}2cR~*oI)1z+3(O#GPr+{zm zeIV8lX4s@#y0H*QMIImYx>scxK|m-sEdQwH7u%@;qu2%N;jjqPcB^ChF=?-~7(gZF z?~_??5nrnh`oy1@9U|sT)dc@8UQv z-REs1A~v|evUSfq@dfSQy=1TCF_2W$e2WI+Aq(^Da-_N!WQw&zofWhcPBz) zWGPX8Q3h+I1F8-*jmPw=xdp2o8mz80F%te}=}${%!d|xkF6kPodm{{|8eoyrK=w43 zjyPCF8=Q4$E1)Y^*>Od${u1B2LQ{W?!&)h!ou|i7{^x57ehPxL#LJ4O=BpoxUCjpT zP+mwvdO9O6#~(O$;C}XXh2eX$v(MzeDVt_8p#q#>+i#=QG2idYPj6iR?R0fZ%<`XQi4R8v3`cu`Ar9Dqw-DcB{{tR zDM;%fE5K{Iyve7qbsPW77YClig_mLG;|h?caq6{6hwg}z*))^Bp@+1>x@|x#s7veY zD2ye9NAQJdXlW^KOLGXOer0-*YcqqacHJ;(48esAN)dcHe-F07Aa+AEQz*EGag(Cf z1b-S4;NCThgwHQUeb{Y+pcWJon1H~cqN1kn zTca`|nupm<4qEn+nR(lM_ulEZbs(9_tN^G>+LXn(u^fpP0r(H!YJ+;{deABLSX=8A zo{>rz-@K*!keEo9SR%nXr54y};>r!aLHvTL7`<@YiK)#EG6zT$KI^VTfJx-=joGXd zRhFmXV!^mkC#wVx4Nz239v+-GZt{D#!XNd~YL#`n!=#w(G3oX- zz|g;Z{yvG6voD2PC|@t-#CqW|b8+)kACBaJ?FJIn;kwc+Kp|xqZDME+aUh!w;*$xpG!!yliO<=6((~+Q$BWUx#o^6aIfE|oWDvw#JNby0tc(>RJLeo( z?)7F)h`v|#j5v=bL)Z6aDYllv6yun~X~2G)j$QmDKEq_(eN~8x1vi?K@V7_MDLYb_ z$~YFxygfw{G4Kgyd<$m<@fI_sqlJ~cn~A{3r~Xd&^vDd;mhPu^9H=VA0O{P*R&x9e zDfFoV1mj|m*KB-@KbzCofLSyWc-wKJ3~3$6eRzdp0;j2sB*#amKZ`jcdL+9esSo;4 z$D(ob4ZM-lv?y0lL*qo)l2h9!sPLn9eZ)bg)Q{CD7>&`-u0FMdg!yaPZ+r$Z_EOtd zo{_*KDKEZr8x6>O4btsWGNJh^3|Y*%Yy7m-83k^$RiajY6rVk}(jLnqH=K-xa;ac# zNSNU%79b@99NknaB*0!Alcix@jktVGi$(#{zXfAtO~+_npgYU7J$la_&)~OYrnsu8 z=|@I@asZ3iW8C!sayQQ-MCo)q>KFqH@Ek3A3$7jq0zSa5AqbWdc9&5LGiuqqo#SvA z^i71;@K!c5&N_7046(?ds0rEd1!le4%=qLznb`fL%ze0a8=FZsc>3uh4z+xMm!K*q zl&fC`!xjHIFT#!q1KXbqk%q${ZlRRY1&s(&F~H%r}5j;`laf12wouuZJKi4Vc@ zd5L&wqX(GQ)Q*FcRnnobvHAEc{HFE=wDGL^H(JDnU?Se9*HD)}2Gcb{Q=@>n8X|N5 zaE#)U++x%R=&vr4*zyQAX57`k99?;^>Ghlv7Ye?G$zNkSfo_5{p+U<#RLd#C;T;{c+QSrT9KZ>}KyX2{>nNqpr;!0xO zJKouJ{Iq)Gb&W^U_A||5{G}&7XA2fh^1j3I+dqp-BDFoKIn@7UhD$yl;CCx`UZElr zdcEv`%ozj>!uMcNy?*dZhDZc|!6?6OVa_Np5(}jTAtAaX%G=XvX8o z4Ihy=F+9a!GmsWfrF9StmX5r51VF_jiT-Ym9KESq)q$gqA`Hur+54(s0vrdG{q%sJ zy;QEwZ2T<5jFO+B=kHIhc8P;gA*%m4e2gdQWz7Lk$t?3A6=yfZ+Uu3ozF3J?+OWUj zhxf-2zI=rh#u(U5m&@VCGr~FNGKNAMnYY!-s~) z3-NOof5Gas4J$d)5bdkj|FXEaO04{Uqk-x|{9pl8ihp>K4aYXIXt@WyGY2Zy!~9v1 z!2xFp50bxCG=JWHc{OiE|ABSoU>oFM4|@Lu?RzrsD$*OOo(fk#${Sof#^hh_`s?}G zI7BBQ(x0KxS-zMq1H~x?PV4oJ)S!HG=ro*`k$rSpxx=gpTBdU9T6@s$JDw|?5YwLs zhwFn}`4+6cHoGO)~NDKM5Aq98aqNb}n-4o9|Sw0<-_H30!mQT9JUPGvGztG5^X zZ&ft8&&S>h=J{EmMp1>>9*>L_J0kTX_;{FlcpmVD$y9xwEOccv7CmvzaC%*2`cM9NKGL`T*NkCslFYqZOEl>Ka#>V#u zG&Sp5Amk1S#G&wJ&q%`pCf4a{*4^baU$H%>DSw?KKHpwKBdOl@0Iv=|IP|Huw6i8Q z$b9WkTtMN1=|;c+w0PBq2AK1xj!4)Rq3>4c*1fu7aULBv0u7TpPo7D#) z9P~lFkWWQn#th-G@9OR)Xm6aue8b|%3zlK>m%Nu0kfiU&+{1W~R{Z{^XyYrEPl1Ps zS5HSIO216GEM*~8&BJ|=;N%5k5Fb_=1dF=%eZ~QhmZmJ3^FEpq0NVIBNqj!eo?muo zY1$UQXU+dpCKW!oFeOKhyEQ~?PqTq@8V)Z0$-sGDPY-Mb6UlznFB3g&Z$%^rMGi1I zB9@T5%>6ISk)yoJds>(P!o8gfmCNeQp#m_R|EEQ+6@~JzyOeBal6POy=W6 zAFp~1Hg837!MS5Ta-a^%)>I2eDu_8p6wZ84__Dot$R zk@?WEUB+@5oyas%Oa1A9k(@}(e@%lQABIsgbjvI+mmDDaaYwHqC^T`RN5j{)nQT~XkZVaki^A(n=k z&j%;JOuqmDT`Ew>FBYAGVz{T|=cxq65khx4{S8F{Vnu~8#n=;^J!M>oHf9|Xaty}twADe=17Bfk8^PzZKk5H;D{=h=-bsaB)d!skkEBR zX{2&Xr(+;Vq+S^Kmq_asXZ~jGEr*Gw0nnj#o&t5_72=z{IXhBl7HPu0D~vnlHK>Jd zWMb;19!L$b)8O+Vh0twLd%d&%=-$BBE%6n`!i?0VYgOA`S#hHaTP<@z7xYONbn0B1 zLc2w6Hm@!6$>Vdlh_PmJ64J<@o-bIPBd7f`)sQN%xw<(1NlkIMTI);BhaUdGeDT41 z-aVwc^|v_$jIhn^|3Pn5mAuC6aAgjQ>MzNrAxg`xt2eGp^i zDMolfec0q1Dze975?t7W;BXVclo-?c`ub<*WLbmj1_~1pWpI+JZ28II=oAsU-M~51 z>|KQEv-Ecu&j+4GrCU#AX&&(yY4%aaXfe6+6h`qC7xXXJs<~Q81#!}tst1!VN}DomzV{-Z<^#X_49=)#U2? z6oXt~o}!M^yUzQ%poUIsAhmGeOM^~&1bo@WOIHN~R_{)6C5)M>y{hvRM9^w}RXeGh zPHz9X!8ckgH#EOFFfsXu-zC2jE95o{@FxCEE67)Z+Aa6JQx8O-ug=Y}FW0jY8)&jN zp++wl_?0LLY&r8pRW)0Pd_XsdH5mVdd8qtistt#5-}zD!nECvbV`nmKK9bHE5W8H(OGI1Axe3XTn*;9ajUTI#nAPgUo=Ll6T5AbtzJ` zeaGH1PvpIpfPkHi$DL*mw>b|7TZ4F$=0T?Al@S0XF5OP-&ljxUK@*W#Aba@Wm8P4HRJUdq(VrU zEdSc~tJU|OG6hACn^#jR;x}*JmczbDifXh`^!!pO$U09y9LZTW1vy+?7k+<7Rw4Y6 zm)+ZDS>xuv9YskmyOBdU@_|-fhZQ2jTx^ihK@7*^W9)~m42NAQs~2SXPvh2oZ`8p$ zN0rD&=v%VDniryT5^AhDC7lnPwtm0b_%+S93^Paq@P9MR0FV&- z-^4Tj|8m#U7*3d?VgiE=-59lu2_h3@%4-O$0CpbB-t0a2Gn1hqLBb3vsppJ9H z9V2HB54H_n#MXD!a^B3A8OFTAoODckrQuv42L=>{3Q<>t<9n?M^5Ur}R8ur(=IL~A z7Fs*cPC2nDHkTwbx?*ZWm`n*&EN&8oQ2gAoX*9(v?sXY}SEB$m%{ zUM!>%q_HKrUs;S#c8)8Sbdmck5w%aV!7mU`8%N|5hOyE%-m9{kcaV_#@6(WxW+j5i zAu9=rua7-j;Ik(8ggKZ&vdPG|FTF0v-eQYOb1%^Rx5>U@P2ISSH-fP<5=ng5kBj1y zg-dd5liWG&f5oowPif`owX=`Ef2ni5d+3L7W@kFl9zedC35$Vu-A=a)aq`z42APk4Y|FV1ahbFt+c?HH$rrKc*l*-g?jRa3N_YPP z{1f8_%GPvSWb{#2Y>~cpD*Q4Dnb>!1r|9uDKipY*4yuQmNZ7TfQtxIF&wt0HrKemhdyhc(YAVPQ)tHVWb z8Hbiy_&tmle>Kl3;JnDClJOa(T&NWQ&zfr{4!0ZgKS zW2&!B%q0Uu$M3>m>z;t2$>e3gw*${fJB6$eRn1TWz}mAgJ;zT5xA_XsHQh4Fb$Jy2-cfcgiB4&KsDv-(&&jz20@$GtgX`kB%}u zb#k24_E3te;q5L}$fag0%=@y0*YL*qu0z2&Ay14qHwsNwrq)OU3_~st<)$d>vE3T5U+5c69u3^D$(5&zb+HhZ*s<`x~G9>v?-T+AGLN2V05(PeaS zh5U}!00T)*@ktBY=?6RYkYxqr{PE)tV)xI4@&7ABu3X@+N# zN5GsM@c`r|MD~Rg5{adk8wut;x!xN*QDtv2oQ#O<&s{f)7SIJ;`}R~3sh^*rRn!(O z8qz*`a=24jQ^{!B%u+*-RhZqAXk#m7A$H;kbnhdlQEOK*W|xg=ztNAOs=KJ6Yy*Vejf;+?ewkE67eX1T`LfLGbc^drr5MShIig*}C)_Z;Y%8bR~(TVy^yLG$Rj z&n_%6zqzUnk0bY148Dqhc@<&XR=XSrf3OHbCk z`2;s~y^%RRV%@f7SGVJcdB$zfxy?N6?qjR%)=FeR5Q()S<&KwuW{FX&Z`X_q;-gEb zoj=gZ?ZFRjw*S!i7TTPfUa>%}t7p(5jfNae;u7GoN{b^1mE(+`R!sA>9tCNkAg<$T zTcQoSdKbUV?_7$IaOA^&kq`-dFdi5P(?>gNlW?V5P<&=KDba+QeaO3hNH^pE)?!kE z@-+%BP#WdrbsHL}%FP^2`bhu*;Qjrq&NvXw_$RY49YCkk#)8D>J>1##7ab@gEs7K& z$C;i76KttisfhYCc-2I4Xl@Z;eIFbTG~}YYg%V6mYk^;~Oj5yEe~v*)E;rUbVk^Rj zr)U~eBvipmmrt)8FHbDy(LifM(m@hOV5!63k-*t(l=xk|ncKiV^WippAA(%zP!F|X zVv>j@UzaSH_laLsLh6L(%J25yga9FE+8g{{4}9m+QEHH230heN_wA_`n7^#_{Il03 z{0!yuDh@ab8WccU_#Wu?20I`e8!*$>i3xs}0oC>wm&G2M!v!6(0>}>Uom~$7pb@+1 zABnos?iP}P+d-%C^)Q=cVp8V6sTV)_A>R$e=(*IgX7HAziR^!oRkyU?28q{W-Y`1N zV*o*M}&DTh=Hn1>-mr&2s9SQ{PL*?!`PDBUT%iO(X{ei|bYasDUmMo|e% z@UXZpPDXD!{4(}8CY&r3%``jx03*yX^b-Ni-hl%6+6RDTUx#FJYJ27PJl91JI}qZ^ z&aSsMC+VSO1>KiqR-weic)fw@zaoeQ_PA(&(#EE$^(C?V{sxD7-hE~f3fuPuJM>{+ zCxpBIbQ7114Thy@N!F8t23xSo2*O=qsn95I!MVLJ=QjlPfnqV0#JWA;Po#X&LI zW6lR@@FfYg4-trdg3$kD@yE)t!u2ucXvY0>@crNyyjt=1#9aX!eSOi{iaVUGQ!u1Lopa%drvc_{?SvLv> zJlVyOYi`um)ZocxhjUmx?u^*Z4_L=eo+bHE@zgw<<42ptlMN;`)4^iOhq5YCdkSQN zzo`?12vQ5YQ@u?Uw3Coq`Qhc|kWEcoe)_F*Y3)-vjrO+spQ^RK;FC8R!>O)&1p@bL z@YGShskU8|1>d0|(XjHmH{l#9fr~so*Kgm$W+xsV5&me9yXe0Q+$-(3*khc7;$;%vEh*32d9-G^K9Vcc?Jdx~&BJt6~j zwa&LfpkJjJU2pzcjE7B5#@`8i4W+k`Wdb{`NnM`ms<z?sA~uogOPE*#!28R|02GFA`e?u$HUK|lil3)FST9u z9m<+qAMK+^?)=-}L)|FQ;ky7Dd%@`p;M)H-0quUCDEj=lVz5%yj)V8GlgKG#+egPAjYBWx)6M46uilaeCPsCC;pyql z%9lckYjQyVIQpQ7jv7F1l{o*Nt?PNjb(}SnZe?@*l%G=X7hy=4ll~crGt}UA407IFl;5n zoOErz;)C7*z8wV)JOQ6!hwAi)GqcTe5oROM{alw7hAq_uY#jS4Q&GgS6_q3iBZ1<+ z3Z9r~%j4-2Sh~eJ>Tg5Rjz-odkm;}VhsVLA#pX#}`P`?UQ9)PMG4h8I=NN)Wx?OU zNxs-!X~d*_`V_pPz^8;zZ^dfA%pm{3gbo2J>nvqUMTeRe_(mVlvnV+tirURuDLH!mq;b_Z_LWhH+jm|$zF^i?=* zrchcb0CeW z5|Dh#Mn;SxFPp#q3lC^uc=p?=5n^RBoO2rDQ+Aw(k7$p~TO{K)2KX=cmI2B6RUGzI z#FHt-|36gRM=CHGl1GeW&LRsqNYW*8iReECr0jqAyP{-Lva%-+A|I%oW|I4nQ| zek18e+q{&fJ3GJpLh{dXi4W%Q2_sFU+43t1-`s% za1E)jQI`M3XE|)DivmbJ5&zYg6a4YU;Xb@MO(Ox9BJ`dh^{j?TMV8W86m8Gi#?=|7vx0m*C;Qf^stZ}4-#e1o^3zO{}huH`DOXD2%i=sxZ_nCJSF|R->0??zXm>Pxf&0d#W#p?yHFwsHTP30 z5HDbJ^Q!>x5SOTDc)lAYZ0Pm6mGob8|MFn-1tfQp!y|GlItIl47t%{}%u>E$O;Xk$ zpz+}%K1?7kr)feoW-ZEG{!gF|6Zq}(AGgGbReUHz;Ox-bvbVdaAf0K4+5}6Imx2lt zX8nt#S*C)3Ka=q*UkBP5G%Jaii&|b(V`T<@e@9ElBYn<}2Ed|779#8*1>3GsR>IVaek(t93UhudcSRINetKFh?YRL~$Oq7VrQd)c#H= zx*^A-h~xTE{Tnww{`^9`vKsvv8UBQ1;;{DgixSgWjuDE94&YG{$}6GZ!-+~*s z(0w?=X!`J7tOzeA9*vWE8K zwDAabEH~W+>Gdh?W`3iq>b=3579W$9S5$j+aCAO0o|<9Z$!2*?zbO;*k3Y;Y7t_{D zmPlIw(3*uz7Qi2#{bz(x-JFE#a28FUC}5=6B4i8$hJCG^jb*H3jV&35%+sxMe{I27 zqy>FmFzjKmCX^LO7d91HEKAUvjDMI{YiX>hPI);pHS5PooHlY# zhesKCK{W=>yo*lvjy6SYQe8zxb)bn=ueyodORZF@hHN|{^g1@j1Fmg{ew zbNaA-p~ZRekK^CTC3KC98e`K+6Aaj0BkRr*G*5TqtTm+)ZoNJGb#wdv11iwA03mXvdlM7IyIMi>wFUjb{ z@#l{;tx{MaJmp{mgJI=+3qIgfBvQAlCNqxbC4&*b_Ul-uM_Bl4uNis(8yky0B_M&A z0~he~N-iEaVr}7wQ^k=Opb%DX_8akv%jl3aBZuOYzsfDO=zQDM1gp!VkN;1elVp~? zez|37X{nzV+>$neR6+i;cZnR2yJ|IDtidHPJ+k^jvhP$LLLs)1XUSppaUW;Pz)gps zE0HK!h^S|hPv$ojr@3N;UvWiA;ljhYTGtP%kNcnkHp`1~(o+-*4lAlHT-HdG8o$AL z!>ztjuCl$o%C;?mDan{5u3|;mcW!V%9NF3&*bGlcZQgzH7jgUN3v}`>(Jv6#9cc;` z>X}r0r*KgW1kh!_MfS7{tcSgJCdtUg)4g!aQp%(R<46obA?mi)3ry{n^RFuuLQQGs zxY|NpITHS%A40v=mgiBOu~zm1js-s@qq=>&8vR}qWd;YZinAVLw^g>VWvYV~rnj0y zFe+R#E=uI|1j`sQ#rXaCMD94M!81{nN5?!Due+)iv4($Tt_TcViHBiJ-H2g{u%vSu^(5ILgQ-=wVc*y8TBT#Rg@A1 ze!JD{=eet~x5NfU?H1vXmD5Z@(C%>;DQlMZYi4=AhgIsr?_(;+OOGo)EI$C61|Q}m zGyb6>_f2H7mXUEAVsDY_jbRwIEn2CM?0V1K-N_DoLic`>^*dX}XGM_x$Dpz5iRC5D zyQ~~TFMKYWWY70Kj4_043 zE(=l4;UI>r{TkaMV*|adHlD=W>*=RF{)I_=T14U66-f9@Tw+p^#`0~Ub|k$2`Lh=A zN{wO7b^vFYywgDvJZyIM>1xi~wro8FDeJW&2%91kUOq6@%*s+^U2eijBFM}on(J2B z0J=Z%Pp&B{3>bNW*H1PgAM}N4`)3#0|6~$QDbvAP}_k+$dL%Usu zp5dHBKchpqp6}is;$m92z)r)DpY1<{WM|C0@uyB$H`*IEHwoC{8ALJ>A|#6Y+OtGP z^%4(8K^@y>NaH7Qf`g9E`>oc`gw7oyC6oJ=BELqZqY?QSrJZf7foda zpngU#yLKnVLx?vqmaBaQf<|(PXoV`iG*Y$p%=XJM^e(L>I z9=w_Rtr9BsuP-zhX`aTVOQi$PX7?LCUlSN4!#pZFKl=@2#&UxEzEwQ6X9V%gb5>K z`^MD2qzHN`Pso~`OHY(tuED;urXbx(Ts9Lk@RC^0JG!viJ^2qyFPp};+23OVX9*v} z0UPps2&L|G%WDFce)=96x@deaxi7doN8rygA7s6f=~EvXP+JdEqSMq9{4jwdnE&et zQ(805*lk75^F+GgicB}5~J4Ze)~^% zkPT_@#w5waRzJXb?1!BQdgG`BN$iJVAZE~G(TSxO2C`QM|8KE34h|G_8di-1+5e{q zO9CQ`R1lEU@PCRoeJn+EXn^$hB4Z_Yo1J4-_WSAY|EfmjgsZ*tKbhY~XZ$z^08lOf z!Zz>$ww?k*YoE?|?15KDcZ7BOho$u&R)&ZN|F()_{H3}1RGxWbTJt^m;A*5I`TnfT z7;f(K8S{_K8}Hks3TD*;uXQ)Ghwjx_##O@O{M2&HjTXuB2`U!s9PYD+O87wp<9w!@ zmWcD4;7x*t{r!lb57bvwu+1CR-iFx}cl0nCcU%aS^5}Uof9iKK-kgM$+pMgFmi(#| zV0(29e&@S)7ut}(-(kCj@?f?;Om^wpZw}lunHyli@z$LI9aYUtzm`96c@M;Q8iS`we(~;8J!uWk z4BSk%iOeKIs?HLOL*bB+;t;2}?}Cb%@95CX3RzRsq{;D#`^n}T#HTXi}!D4e?=nD@qYYP7GDZ#x7uGUM7vn}7D4!VdLo*~L}2a7 z>n@ps9$U4E@g#w%6hx-0Ix+e+J8mwfkO+IT*r!JBk4@c?MVN#-c$a1;rs*)t$sPBh z9E$=^j8#K@qq^d1g>WGXokKY)3bYW3x01ES4fY7SH_F*k-W)pJtKO$q>>8S@PdrCC zOv4Viy`J>tGp=R#D|Q(>RLHY|-cdh8!xJy5o+46v?JX@1B09oGXJJ<11Spj3w@tjl zNApiH-w)<-B7OaY_X|NjYqOR~e@um~mKhH?X60=R46dp$#9CzgT>o={EerjD(CE^W zMMi7YxE&k~%|vdA??Yt5cAVzCmd|GwoMR|lT8gff{ROPMKJNLE&n2e_QT^2uV~T;z zm2fSXhe$@hGVe>l)v;Zp+tWG3_*UZ-J%%3r3MySCku|J(LO8&0nk@9X0QKCVnk}K0 zVNBKxAe~zyzKf2|>#wzgsvEb4!?#v58kWQQf$Ie*pm#Y>e(2{X^-?H>updWauRM$L z-oH+I1xc@e-oCb(y*ZFiiKFo@2}Y={c>`#XX&UJ^$0F7`FAxpT!;T<};FhBJ2CX5u#=#67uqb2+H_NS0$_wN7- zqjnl0l7Cz!kLeZUN;g%rxSp|WL)pts!4!OxcRV>;qxt3J7jLA^ne6mWg$33-qQ{1; z>GBeRAfXP5o)BXo6w zz0z5*K~haqbdzDP&X%o_G?lu~zV8(NEO|;$Z&u5L0b=Xs#wCw&pb@u1bXB>}Gnv8- z!b2%ZX7;TtNQAL{Azst#2t1{EdP^T^XR3MCTCJ>XX{!zbQU_g601z18AEW(o;M$E z?jRBC)89CdwY1YIR)b2~%aR~&mTjTDznx+O94rUArk_vOWhk{*5-cNXU(w!hExwA>ad`~t5k!F6a6t3jqTG>mogANAY__^`Cn_;PcW#z zDQSG89hNF+evI8&v|mVb4AnGaS2*Zs$2#z*(FS4%Cj%{=J-OAWCG?wx%*r7-Buxg` zxyecsMD3&OmEANR+i(VMgOrxsnI)sRUPfDn(U-byd_SI?_}1+;n9xw@FM@SUJQ`s?Xb zJt7>fk3i$AfA3W{`yKyLh3W+I6F&v{70DZyL)K>IG)+n2z$Bp3BlRRE42waI9I-z5 z_kqb%+dn2O;Ni`eGtOUT&gF>;{!uw!ze=ghB;9;)3aG5kZcTX=2a71{ug%_)n{{U{ zmzN)^x8mc!4K~_HiCH^jewyv%+!6SyL=kR(G?p*v`uEBC>-AjIFXO+s;D2JH|Aqz- zUl5UI4WX&92tJI!f(nBRV_Z%wghz7*LTtWoa4Szkxl5*Pnw5Xk0HgfRycmYxl@3qN z(}U%4`_X>&n{*_9`?MT8tFO6ooZju^wcFdhvcg&>@^g-A{BuE`ic&B;*pD9K$?Wt{ zrp@eRLawT*&vRy-`ffhnO9tW$rQQ47uSH6oF?EZ7=8?VEl zTpzUV*8AmZ`+Fe?@rQPW55J3-DeF=OdccQqGB%7+Hd43Fk2asO5at1B1;ouNa}J^t zSy)s0thO9>)rl2atnuqb{etr}wq}cig2EYm6UbE(aF(QynLh<51WdPsa@6GUc8?58 zI+B(`AMfgacE(HO7-a|<#k}P%J-KB8f8&w{uM&Y(O^R=RTLj6B7oKR4HLEuEt0$n8 zJAu{~BxR@dNn*k?m!r}RQTnHoxhL00T3JN0PICj7g)~Gi&->>F*oqW;n95c@0?0q` z2&WJ!Fj*B2r%9RO8v{-y;7+y8w=7aGvSwpk)Of;S0d1nHf|$7}+~>;>!oYYVjcOX& zDs|QR=h+CaGgnip7B)keE~G8J(xW5aC|)>ZNQ z7Zg6@%3zGSW6JtrdPG%}NS2_Fr1o3li2c2?hLC_&3(BUrch)?9{NgOGIcS^L#UbAC z6v0!AXn9|Y?p3a153p4ajYGwBo1hlGCuU+L;j2zq5gehLO>VYku&LIzLkh32|Umq&P$K%NWazfL$6lqNGMAcQz z7LUy-)$6sOwt+orV&+9psLpr^=)KjuB#3x7e-9m6VcXEKm9qFAc`@JaAY99 z2g>6iUHR`Hmd7$OppX?v-Q|Y^Nvak?^=#jea=zX3D4YGL0C7r(cvkO`{I?7E;rK~pTPt8x`QPU4MOcHMyLVR#-YgH$yNx`bJ zsGvKcPe8M97!KF-#uWV}zcASIC`a{szi!(rB9IfwY^m&v6I9UgqIBMle&Q(X3bSsH zB-(F+p}gZ=0OWF60DmO<;%UxDES2HcSbyB>Q5w@$f7QzusiNC2Y=@oB0LJwm@Q_;Q zRigfpdJ?8}+QxKIRBCg~+jT9<7Qj)?LDezZHnlf{2aX+nQvXF7S^aY7R`=wXRSFi-tW+-uK5ODRn84+naPTUVl`C zRBhgJQOXUo1^9VVcY)#xK?EW1^&f|Fu;~hF&=xL2}$NV|5 z{hKV?rxM?oz-{P&ChV9Oejy-QP!_5jTR0EP%JSmTT*6UE-uigT{ zMFISESfGNOFqn{hcO8ukSg7Rv;+D3rIB|^Kd?4d92gMhTIEU zs82ws`?;7H+a`Dz_$I7$h|&ipTRD`z**ov+hHqfdzJsi5_LMDscunahHx z;I_X}#w;~e6vWD6B89VU6o*e^h!n2PVyZKgg>ilwW6mr8#^ToxTOpq)tz8uP*z zo%1qyGVMis%qPWmPG7im|Ha<;M-bn!%sbfJg89<%G5NBDr=m+VOsOgxnD!+XW)-w% zi3%FUT9dMbFJv3Zl*L#`SxLpJ=~5_M6UU4v>xESp+{8c}VgsKNwglu5)O;b5jfA07 zcQSy%2tDEn(4Sd9=ijs6n(F_0OM!K;XS=xY0^88foQvB z$PJ$&XSr$O>aBAO6v;nD=4$mcP$I)8gg9m3sG++j7AY)=`{sC zE6?n7O;8Nz^UKMXr~oDmyv0c1DMlJ2?sf!_`{}d7Sl@mw|LVSARd(i)1)^Tk7#H3} zB=Pkk)JfFhJmSORJ!KmM+v%qlxMsM5A3T0BqiDDXlYr<}gj>ItzPV6=2GD*JmRB@U zzLr$^fd$IRTXN+cI-O-xe-D#o#?Wdn4C*hOSH#7r@G9T={k++w5b)-J-Zpp$8r2dF z{JgvvK?j~njcsq&ppcM&#p7ADfL0EN{s?~m(gG)iF<6JeWC_g6noo*9pB@((z151g zt^CSrHM{>*ez->loY%ZmmtycdN5np=P{BK2MVRY^5zcX=IQIm-X*s4c&$>?PZY=lQ zPA&{xCpyfdW#n&a9MS2su#frm1Gn!XB#hfM8W(A`Fn z3R{_3xB%Rnz|23btjczJ1Bqssd_fd#Pp{&llG!9|X%R?!Ns+2ht9f7Cg^DpeSn36Ed z9yd(5%24hOtIO=2_`0eYYkltbQ2+ZcN}s)`aCj*c+oN_uOSM7kd*xI%pr|A1cx|dd zip1;pz=_cM6m)0nw(_l>bbTEtK<+m@l_vwK9CK9pLVxL@O%vfSR3Xb#%AEtoZIG&Y zIvYR;mRTXq?^%B0^1|bl1aw^jz_YmfO>M=U*Pxyo`CedZCj=d;)kM38L#I%~Uem@6 zFysl3+#}OrE^Z5D2@|YZC^#(?38l=-2gyb1=^=7aF~%>Yro|6ovv-3DR>mlnl}oK%uJulW3P+}=FN5TTY_|=MKN=bLx*zu)vLTrOPZ#v^7DWU< zNe~B;GiB-c6Ry|0Dw6dRB!MZNyS5b>%ZT(WB9Wx0)P6_LroVA9pQHUR{fruTiCnz1 zdfRkxjk6EQ?Bio%Bt(U5d5PzhnDiHsJQjwcB%tF%UOh6s*?=ApBj5vz0^xLx5-Z4eWske?}aYV7JcN`eR|Wg0_rbL1!n zm-+ms&yNV+!MwQ1SAUa^1ZMn&>?uw;3YON#6gOq%P$Owj4wI`05Y>n038shJE!|K> z2kv&pqz-OM9O2VA=*79*k$;nujun?WB^nE~bd)nMfH&T)WHm z;y4Vq93ihmJ%VtN=f(bUw%NV8!00;~Od${b)9G7-$$=5}P~y-*CtU4RcGCEp0qH>G zblmxsjpWgzGjm46EXq3lHjrBXmj&>6_UwOI0LXK{keB6T0#XDM^oMBxUHfwSqjE?& zHRJ(fNE*Q-Hw$@+8Q^ixJ(5lE$nE-n6^Vifjz|4PpY>jCXRpd5y|?-W_Gj^`Iq3J} zpIH;l9q6jTwO=`S$(0HzPFn)((|Y@jhZzboOZQdJTK_@0z;HA5*5o}HNl^ehvOoiY zi1MbtYxy{%J!qn;zNWTC2G z!Zy^Ce3t%X@itXSk=nfevWQk$-?jbYD}xjk9qy*|&+EyJCi-XT*56Xy1d(0~=2T9; z4+$!Uk#nhOj2lqb>Xhm9=+-PmtbEJhU>mUMuzUN3rJ_mVp*o>7y?M5kTIq<(=s^B? z($pT9KRIoO$EZ^%Lj|cypivwP9cR&jn!eImDs+0YJ7qb};0w${hO8xN!2@*7B&k22 ztu{e!fiMJI^WtJa};oo99)@Ye)K^F8o@_OtnoA zQx-jnU$^lA;?!)ONl=l0m~#8V`KujXSx4Cb?jp zl6VgC`EF{1MlJal3kk^#L`;b5H!~;P9jX*1tjkLHl7p!c=&a#B#lTR~j33AtIH5!= zK|a}aL{CU*5t7?O*GPAxnkOvmSc=q`c&bQk3IZXqk|B!~73qFZY#4JdczfdIB{CWq zOrUznL2p>uwFt>-!O}@W2YEsz=f;jVBeu(y@goklj-N6Xwgb3Bw(5^_sSdb``Ua&< zsEt2G>|*I59Y-6h)(y+qt%5!q(*E2aRU%~R@h3f~y8*C#w@m z1zCB~r~a6iDr<54!iw^z4%{8Zkos9@Y18Y-QZLW5_hZJU3^{)IxSK$&^m=hu|0V_jv4&YEVlne+-?DlB5Bc> zHx-oCaa<4Qqrb9`aYE@Zo`SHNP6XxbOB!eW$K#zjide`53Au|5?uv{ZhYO#ia5YLI z6k~DAlV8UJ7deZ5A5)o=AqRpFbo|g&mOg1bzQKwc&n$dr=GVnuIM}#yKfM9^EbkLK zfXrw3Rn_2attp826!IQ?rpT!zvSJYT=he6pxs_l=mmc#{q^8sMiT&EV z(>Oy<)!<|nxcJN9^up{;Btlx0J|k(o05JFK?iZiUeHv*;@YU`8Jq{re;FbLE)zAc% z6kHkH9>wRweT0u>L-zIMyBk%3tDo)sn$&P)5PyDO=KnXz;pBUWI}(Ay3^=#<_N-nu zLGeldrXb^1ySwj$NuWHCjR5@5zvvIoOrAbGToGZj2_vzqOReel6;+ns`qa>qj10lya{=vR~ zD*k~(00J3zgK=Jb#V`0?-?BEoj0=4`+^YG*(os=Rd$yE@yv{lMR-3f-W#2$@aX#^R zo_oD<|E=>#u+wtc$X-*t;dI8K;RmV$!QRb_*Pb~oi{;EPQ5^|)>QO5vC(oFu_=fnK%(lg;=l(t(Jiwzm5#yG)6TP4j?U*fQ1Mrx&9|W=5YO z8(O;($n60Dc(RF}t}e0R2iIp@e@~H{15!+|XpcUcN&6o0m<^YJ5?|jh-{q(93pd!f z)QPN)>N>Hx3B07YH6dUib6h8G?G!lp%0H$AqGm#46fisc5w+M=b~Eg zh_3uMIU^?syu_{h)kU;;3g1v{%m-uNX6XzcXX231dK@rt_1UUbne* zi~1MgArlU-`Wx8a7PKbaOy!OF)&-JLZ|*Kxe03vh_M(XTR#6(#P0>9w^drY-1a+Li zY2)h}5oj0B2o2u!J^abv4At#{A=G^%$+BI%+>7trmM>4Pn)4!qsD9<^5Cngi z)Vp|s2SQ{1-X;2%@njHB*+oqvKjs*p%W962e~&{z1hCWLZSP*6^>JWW{p-ays5ox8 z0O>nyz~%hPJduFpLO1pnKwgiR9%h~;i;7?=igi8ndqcl<0o1jZ5L_~*FY#(m6+0yI zkueNB@a9yJTrw$YTMW()j;c?rp${@m3_)+WvX$53-kDslJ9_qHt1MC=d_XI7THHj;Ru>J> z@%p8_12^(@J&x?PbXCUHI0rtC%E68*`hYFoPtnNTbmgDXN=>zciB8eL>C~apmo&xB z=(TPcW1HVi%RAK;A)c{uJ7r_zOkt!LVg?hlZ1CGO8G-;58c_@DPeXpBU%lPP?1Q&M z>wlu4!Iv%>dNZS9f4RKw$#09Ut7R_OnZlA2V(c2G+Njx)HgyDLj`ov4JHQ# zoikwqGCwn7WI1c$|8T;4r3i4wOmxj}5IohcMI14*-Kx*jSo(Ekqe|5ghYb<=9AXeb zagOKYcb^wcOezVtxL;zh3b;VeL|Uza_lOMYXqaEv90(Op;t8Yf8mwP@etwf73aVoP zZm?fzScbE2pnw}_OT`Nn!=%f3IInT?gq^hhPJy+P{1)^(jQu3Ws2I9|M~m3*+e>VF ze1lQMev&r*)7fXvvlD^5iq)nZUs&sS4Tuc15=}c{*|?`4^N0*AWSF_vON z96)9$8M?(Gq$Q+Nx@%}bkVcRa!J!)l=~Nn|`vV4$R6;tW8w8{oco+Zg`^S3gt+&>j zwa%V9`<}he-6wwg%)NJ?Q{b*24!KzJ?s)ITY{kksT(5~Jk&!&_%fsur)I)*}ZXoJgew?=fV43W2E_9nTso^6f0gnh4JxkVpkk5$(rV`?#F~|h(a;{0Ayo*h=`ixK*>z#rF9<3Ga{}nzy5uF z^JuyZDe)F7n*~r+1Um-KC?7#~7G3d_*;97-G-h6ovgo*`%--f^4ka276%j+zt|W=C z*OX&6^E{%DFVK5bi+EHx=p>VK!SPhK*De4V{&_@0bFZtOyXyG>Xz>FpD-*n+kNLC2 zz+-b}64Y1R0H0&^A#_bT_LSuQWzPDrAKqzNF3m%fGOz_lGGb_oKEqj)fZ=^_nnAE2 ze1&(G6fK#SpOu&l58mQXS)VRJNj?jx+=G?!+TOS>qeDlST`v(r#kBa&D87O& za>Z&plj(aiuN*&dt!jcavm+%U(gM7Qep#+BjvUE+%WWaw6iPaPH`Tf8J2llAZ_|d_ z6r`%sJuSMx{~!W7oRfdwBpj8sU#vdf@?lch{m%MT5Hhnh{Cs`2sX|RBHq;*Sqrr;a z1nLuR-)g^8J6N4t^z3;e%3Bv-oKHk}nhv-6$Gs)yqM|Sn8`oy?kN3Wyx!`8ce`Z6i zjUb>FGoQ=~Cu&Y~e^vI&tz~wR7;92TZY34(aER+i@4tFJ!O({^=(XPy z5FSeT_ZXZinZwt2YsApwgaN)3B71Bi(m3_@_Y;yph)}=_Erbp8i8Fdy!W8^tqmMW3 zZ9&~rLD$w}q;ZDI!%(v8TG z8LD7Koy3Vq!b;D^$zD)W`L0Kw2j{e%(mCK*lRdnm`YeB_n$;@j=8zrmwB;qvoXRZZ zz6}38yW{S@BkgdinB4Ll-w;Y--BcEf9~7 zEV5;8Fq3{{iBg&saa6#t~S=LigeYpORQ*zgDi^CXgC~zLs4}^f z@UM!veNplZW51j|DF~G@E@r^|&FAlS^CXX2G$av2e$x0iJ43G&1v8v$2^rxiz_-$6 z*r5nMe#hC}%z>y7RkZZh)+~ljf(%!emn>&7Wbd7fGP-!m#HB2qp@VJuF)scwHjlX- zFFb6;8a}YY*Ji=Y&UHg=do8q47-d2#PMoQwgCHak{Q9Vdqj_`b#7FjG;$Z&= zTF7ZH_!V0H>9+e(A0hY*x)y}|cHD4XK5-wGx$Wv(21xYGPw}yZxv8H`C-N%kkV!{m z5zFU8@303T=&gbqUD_Y`4_`JdC|{Lq?rpL=bM7{LVvyIml$MqGWiNOXiXOL~OKz+4t$0VK^Wszgz z@}1cQ`=ukY`W}L=D^?f#hC=si5+=*y;T|Dl$7_ql^GvOK>vppC%Fd5@QMcC2^24Ec z^nn<*&Fxtf4r&PJl0XSeGf@)dpt_vcODa;b=aX0uURZEJ9=q`_axrJ=J89?UmzQ=a z7n3a$;81{Z7ccFaOtN!V5TVWQ_v0s_jGTGGHOTbENee1hS&c;EWc7+}U?ujS51FI~ z<~~941+eu(=?2CX-J~PNAneU{1Dem%hunZI{x&sYSmw&8B}BIro$u&>#OEUT$gSom zI?_rG%ae-e7odygPKde5KYl=yhNI=U-&)T~N)Pk+QP`yw(wQUknV0$LdL;Ek3O)am zE+~AD3Z`HfQ}oQM9ZSlWkOjpjLOF>oVZCP$QyIReSBm?WR={6n0X!O*7*g5yFt!)P zpdsWOQe@?(G>WQKI?|KDQ7=0aEQgeJ>`V9Nd}>;()70t3tI!GoK${+2(#w)jadQOd z%Z<)kXIa0XE127KGpb<0sFcXsV)xq-bv(vmR*#kS-nnx|!;-_fq2<&%e-|##t~94r zPPkgSKCTAKn=I(Uo57v&Saes|C42tWG)fmAC$i6+#7B0H>^bb#1ajCLf!TcG8-*-r zSOh77d0~B7aYN)*B2mW@4V;jss76;4a)));Hi47MbiVG_dr0qhnzppcmf4v&jy%Ym z30n|cVJu-Sex%eioI+581iT;*NnWM5wE&v^YJSzEth%%SgCss*si|yT-Ko!H3sZ1Y z2!18IyM^im%7 zgCg!Zg5IW&WdeapUAfOzFxcNRCB+u<*1?aN{%q+%s~YU^-K!-9{?Sdj$Li_SZM-O; zm^U~m+ik)((U5#yt|ohaosTu3$ZHVH+=pw@;@2x@nipJ@$IZ+E&v?>MM#?Y*q*-ng8}a6GeK)EO&qwxaiMKu{x2bSb3I5W{^w+iY zjOt2rMzQ_&FuBgsPVl36qsM*g2A&4GArxhMG5}~ey5wk~B{B(f(L^U*!GzvCqDT4e z`|3IOi5mTbPg!rFizpB&hA~f&FjgX*j&gsW6%D=8^7_ONK%8qQ+0pfr zM#V58WcopoW7s+Hv;Yu9An!}yqn%$j=!9kG`GuXs%6}Dl-s0Zf3|3#huB)Yk>-|Cr z|5x(8KQ!?@pc264?B&m1hIXFB_i&@@Ps?c)WXh$mZlM+ADuOaAe(LZewCPr;_PJI-BP+S;4D_roH}mJ>7yX(=yQuL!ccTq@4i4EG z?H2JX$N@l=Ls??Zyg0*wH-C_b&?ss!?S3C|oEG}ss{^}GR{F_`j?&ZUke-7jGS??s zVY=32k9zt)38pBor)l3-yXObU)YQRhO?!72mBeVOPtN9@uR2%ESd;;9oK%TeN@bN` zCn_~)1k1bYMmH>8Ok@F#c}KS+b8}ao)BxisR6wS@a89)AmudyxhnSQqk*Fe_u{>Gn zpMx(AgWdRMqmw@&gR-@DzShxlx8?A0K@K9G-ufI*1d?Sqyu%Y=rySA`rjj5BPk&jg zN>`}kxG&N5>_;`D0uQOgcU=Q^WL$AEMkW8-!)c6LJdI@N9wB`(&w1LLx z7%LoxaEZbkIU=-X5sPF7jj=^}3V>W9hB3WBiDT~42?w_-Q#}%N59T0rQv^sAl zC12&%+?x;+YMc~kxb8wQYD5$ra#=a_Fh6~!K z=vB~H*Su!RRsQNwP`y)a5_aDC<{8DKZeg|%Dw0znwU1rD1WiP{^sH&4@PKiR^f3lo zL|lg;SEykhF7^pw&3!IWNbt${MxrbY#*3U`R!m8U@^y@Y18s0=;=rUpj%T>DJ10R{ zo~nTSh({c6C)(?LYre%ipYvH1_&(RI%1fDuZ-MQCl}k2aTbQt_3?J!;1>4;O;x3hyBtgEc4|YL9mB80aXM#3x{fY8`7j8KMp9!tBz?M#W7^r>GwF;Asvd zQSCJj6krR{RswzYyoHz{bZYxGooo!EeQZPs?!Dz!f%_8yc_L;?Ie=ke*{kx@IgatS zahSSy65psu%-7a0B)ZMB#X^{jR8>q|26b}EJKCa)cxnZ~w2kj+M=}**2h2hOz>C#3 zKvyRXX{~?9+r!&g@%C9%CJxO$fvcYkTNj5SP*KXTH;o`U5Qemq)XX{}wzTFuvkd}w z#=ia0-4an)ZBh96a1+^Gv_Lz=QzBee3|RIJd^BeGjxjt{!Os=N8K$4H?pP*wK9XeD zMtzmp;;OHqHP!Kpo^dD!WQZLAXAqElp{~xwr4&6K(uaeBvO_1V=e#UUbpUX&WkVD{~-8W&$GyM7Z^vq=?(5GcLX<=TRr75eIX zZ@6JfMliK6TEH8Yn7xOn0}ls+@1ihZnL&_Gzd`KnfR0s%pEM`)7eAU_qEh{j2>~na zqTaTGU11p}ZP{%XciJC5nytUv?y5Iuc93g=pY-QiLssW)g3h{Wq#wVHOcfAvzP1IW z6P2Fcfl1&KADR3E;IV;nh_U_z}%PG9^&20$G zGS`!o7}!RDe9|{J*pMVby|eNkh2X%JA=T)Z}N zf*ltnAu*7OII!HSf+X^?!3WlT<~i1^rZ-fHdCyNQDlU#+C^dqm=v_=o8E-EOc=d4f zad*lS25;h7GFU7WM=>n%^{~~VJLP=F$GnsgyAqHBnt8!nr{zAXx@}0v%3i^+<4O8s ztHf$|@;%kiyeW<8~lBg_7i0C{blO3OjmKmY_7J^jwgb*?% zYb}g*L`9k3whRBO_hPYZ{Vl@quRKS+vDNg4oR0|Ad~-V0Eh~Y&^B5O;r8kTHm3&JN~CpeY9O!K96$Xc9PipXH+s(b@Pl=?rdI zFXbF5ytO)?djVK2Ceqw(ECbk&ex)MmOTt?&*`zl<8+jfGd7>wOEGyG&B(DP6A=j8} zn?9Dle1bW4qIY!eA-uJedCUJpvO+5UUv^AE>j-snVDjik{tyuufGi#vWl_Y3h1`6- zuM!2xmxxHTkPcm=^8ZF(J%ot8I1NNPQA5SaYw`vOKq^<}Itr?~DrL}uIT*qkA0~G1 zR)sDxZ)G%k`1>Acs%5y(8Zm`)AO75S*&1Od@SLkhMTERJ40~{qoyxv;1b-hB_SAF_ zZ8aWOYgG=b$WhSgJ#l`mr`rOVpcNPG!iV`tdeXYxzf}wVC^IT@-RnTY51)GAn~Z|e zzdW(z=<3Vm#OXMI5!katGwNWX>)d@(#;Sst+pG*eR4;9qec!X5jZw2|LhFX)8R$uS&P z##fa7+4@+nk>n2Cj}|7mapEZ!8*%WHmzdOcF&i9uURb#M;U*KIk9{zMfCU|SASbFu zSM!|p9_!nRqV z6G204)*sx@(Mke4_4|~gr5^7mIg7xhHx<0RNMYk=Ryp~>lX%7J+Djn=>%YB1kP)V9 zPGi3*;3E-~QfJpmSnvR38!4`5g;v5UKm{Y)ComMoEx!f^Z>nCBH*)@Sf8Z&F`%xRJ|t)SHBX znAw_YCDcd`pP^!tL$e|Cu%s9L2vqIKZ?&KpBqBIN#3_i)n>={j@$8}B92d^IO7>s;PdXulx)Ti6$*%hTH%ruuX{@oK; z!x=%*8}tR;FQ2BNlEYuMe0FI-tD?-NfnJm;xNk~4p7;6H6bDs)oc3^(jPBanknx-R zUMO@;2ld(IDIy_wn|-tN&6>TmLbU9hxnP2kMzqd`a$|3`F8HB>#yf72={s%e9Y*P+M71sfBuzMF?__) z%}9-a>gV+z{e|fz!`UphT1fW(F3pFFC@OyXBySEifl-QLWl`#T=hHETFH)B! z58?-lifu|Y8ChRvmku__OM|Cs-e;}8<~=y0giH6kq1sEuHed6676GGE!Z-k6h4x`N=BLDN~@t3*?S;&?Bd;{ z@YIz}`QfS}NE0_6JSu&1Sa_#@QGKWYBA1xIZUW(M^AuG}(0j-G_%L)t#)E6mz&Rbc z*~-};PYKsJ<)AsGen>C{<>wja{B+yM3EdQW+jLCi+LyN9W&+d_9`mTMC_cDvImNnO z66V3#_~nVN$7&68Pyo^p6mOYav#z9^68=QTcKHKi|5ZeWN&bqP=&~ebOqZIX0>=_2?9F)-wCBwSl+9laXXia@$Vc3vO-0f3^=4WHC}{4GFmIVU1wSQ1mEyk1jn#%A;pwAZ7p5YowW&`@FwDI4Tx(wG7gA2`y6`O7rsgWkL(_8q zdU)zv@a#B>$bt&kuqh@Ibz`c{HGr%{-?RAW@%pre=Lr3V2Oa`B5cPc-e$0N>?o)ej zTq^Tu@Mu@~@~C6M-G-~CbcPx>`cs;-{@|n>4qsxCE@yeJ?AW;CVER6@i}N82U5pat z6VA2at@jf7frd9;>%(h<%@+jEjP*rk>Xwo1`-s!Vfk|jQ>-S4^*uGu|fS+{ji)j4RZUKOp+ zR^R0+p4&iFty&AdC5HRGoEY#`p-E0Mucx`ZQg3(OOu$|%KC*#_<^QtX=SKZC!)?Q* z67i@-2y$}O)4*Rwy+TI;Q;OJh$2UJKUG4HXY2I{MFLpH{a*srYts{$NIqDUu9qy|p zK^R2$+2>94dZuc3O5Y0#dmO&MaDJ<2GvBpRptO&n)*@%o{Ht-(bxfi!@6{DWNfXV` z?ncmd`VP}JZS&V(lEZaQ(=UszrP6j8d{!vSlLUIzK9a;6lZk0JM|taREyfwA81i^V z(hwhwJDm!5o&ECtOsljP@3&2TjW7Cp^|MJRcS1pXq-q;oNBBH)$TbDf^Lqn+SdQd($t$#=@($u1h|9_OHQ0 zkG8ggM}Fpyz14tEu7*sATZR^14jWd~R6I)k0y1(O%TEzCuTN^NR1NJ_NhY!QCj7;c zB4r)xZc3TMhZ%FlnyfF6e7U<{vi!p~`es!QyhXAT@TF}-Qm%qcTqYkAa}%pKdkbJ% zcV~Xnp-b=h+Z8+*?TLSaM|v6Yk!pI-X8M*>f>dh9)$%8}uGD}HqqX=J?qy-kvYB`0 zPOc`|(RwTTK(msAZjF~jvqT^&@&swI*&|Yk`az$G^9tzGve(tNN#a59%;AKy=3Is zs|X%hy64h$n?s?vk?LQGhhH_?z+3(BBG0b{KyyVm7~+BxUQUuhZWzEvK}J=&Ov>!t Fe*x)>2n+xK literal 0 HcmV?d00001 diff --git a/docs/images/fritzbox-dhcp.png b/docs/images/fritzbox-dhcp.png new file mode 100644 index 0000000000000000000000000000000000000000..72235b51219616e89ccf96f9d12ec5fa9ab89867 GIT binary patch literal 41058 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

)M@bbbm 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

  • 9Ynq<2&Gn2YA6JoNN4C~( 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 literal 0 HcmV?d00001 diff --git a/docs/images/fritzbox-wan-dns.png b/docs/images/fritzbox-wan-dns.png new file mode 100644 index 0000000000000000000000000000000000000000..2f04d4daebcfce0a33c63cba1d9bf6e88b486f45 GIT binary patch literal 27213 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 literal 0 HcmV?d00001 diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index 17750be3..bb066953 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -19,6 +19,7 @@ Zum Einstellen muss die IP des Pihole als "Bevorzugter DNS-Server" **und** "Alte ```bash Internet/Zugangsdaten/DNS-Server ``` +![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) eingertagen werden. @@ -46,6 +47,7 @@ Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz ``` +![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) eingetragen werden. diff --git a/docs/routers/fritzbox.md b/docs/routers/fritzbox.md index 852654f1..363494ef 100644 --- a/docs/routers/fritzbox.md +++ b/docs/routers/fritzbox.md @@ -19,6 +19,7 @@ To set it up, enter Pihole's IP as "Preferred DNS server" **and** "Alternative D ```bash Internet/Account Information/DNS server ``` +![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) !!! warning Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. @@ -44,6 +45,7 @@ To set it up, enter Pihole's IP as "Local DNS server" in ```bash Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Network ``` +![Screenshot of Fritz!Box DHCP Settings](../images/fritzbox-dhcp.png) >Note: Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. From e3978ce6f38a4e87037225ae44ab1e001d66ca3d Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 17 Dec 2020 06:59:03 +0100 Subject: [PATCH 12/41] Fix markdownlint3 Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 6 ++++-- docs/routers/fritzbox.md | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index bb066953..6879c8cb 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -19,7 +19,8 @@ Zum Einstellen muss die IP des Pihole als "Bevorzugter DNS-Server" **und** "Alte ```bash Internet/Zugangsdaten/DNS-Server ``` -![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) + +![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) eingertagen werden. @@ -46,8 +47,9 @@ Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz + ``` -![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) +![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) eingetragen werden. diff --git a/docs/routers/fritzbox.md b/docs/routers/fritzbox.md index 363494ef..c5477be9 100644 --- a/docs/routers/fritzbox.md +++ b/docs/routers/fritzbox.md @@ -19,7 +19,8 @@ To set it up, enter Pihole's IP as "Preferred DNS server" **and** "Alternative D ```bash Internet/Account Information/DNS server ``` -![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) + +![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) !!! warning Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. @@ -45,7 +46,8 @@ To set it up, enter Pihole's IP as "Local DNS server" in ```bash Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Network ``` -![Screenshot of Fritz!Box DHCP Settings](../images/fritzbox-dhcp.png) + +![Screenshot of Fritz!Box DHCP Settings](../images/fritzbox-dhcp.png) >Note: Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. From 21ef9007ed13d93d0101191051d9a8be5f73e6c0 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 17 Dec 2020 07:00:39 +0100 Subject: [PATCH 13/41] Fix markdownlint4 Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index 6879c8cb..523725b2 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -47,8 +47,8 @@ Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz - ``` + ![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) eingetragen werden. From 1049bbfe14df59cbc8c2f1cb2292ecc0e927cf1f Mon Sep 17 00:00:00 2001 From: yubiuser Date: Thu, 17 Dec 2020 20:36:33 +0100 Subject: [PATCH 14/41] Address DL's comments Signed-off-by: yubiuser --- docs/routers/fritzbox-de.md | 40 ++++++++++++++++++------------------- docs/routers/fritzbox.md | 40 ++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/docs/routers/fritzbox-de.md b/docs/routers/fritzbox-de.md index 523725b2..d49f9a75 100644 --- a/docs/routers/fritzbox-de.md +++ b/docs/routers/fritzbox-de.md @@ -1,20 +1,18 @@ -**Dies ist eine inoffizielle Anleitung die durch die Community gepflegt wird** - -Diese Anleitung wurde für FRITZ!OS 07.21 geschrieben, sollte jedoch auch mit anderen Firmware-Versionen funktionieren. Ziel ist es, grundlegende Prinzipien für ein reibungsloses Zusammenspiel zwischen Fritz!Box und Pihole zu verdeutlichen. +Diese Anleitung wurde für FRITZ!OS 07.21 geschrieben, sollte jedoch auch mit anderen Firmware-Versionen funktionieren. Ziel ist es, grundlegende Prinzipien für ein reibungsloses Zusammenspiel zwischen Fritz!Box und Pi-hole zu verdeutlichen. > Hinweis: Es gibt nicht nur **die eine Art**, eine funktionierende DNS System aufzusetzen. Konfiguriert euer Netzwerk nach euren Bedürfnissen. Diese Anleitung wurde für IPv4 geschrieben und muss für IPv6 Netwerke entsprechend angepasst werden. -## 1) Pihole als Upstream DNS Server der Fritz!Box (WAN Seite) +## 1) Pi-hole als Upstream DNS Server der Fritz!Box (WAN Seite) -Mit dieser Konfiguration, wird Pihole für alle Geräte im Netzwerk, incl. der Fritz!Box genutzt. DNS Anfragen nehmen folgenden Weg +Mit dieser Konfiguration, wird Pi-hole für alle Geräte im Netzwerk, incl. der Fritz!Box genutzt. DNS Anfragen nehmen folgenden Weg ```bash -Client -> Fritz!Box -> Pihole -> Upstream DNS Server +Client -> Fritz!Box -> Pi-hole -> Upstream DNS Server ``` -Zum Einstellen muss die IP des Pihole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in +Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in ```bash Internet/Zugangsdaten/DNS-Server @@ -22,28 +20,28 @@ Internet/Zugangsdaten/DNS-Server ![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) -eingertagen werden. +eingetragen werden. !!! warning - Die Fritz!Box darf nicht als upstream DNS Server im Pihole eingestellt werden. Dies würde zu einem DNS Loop führen, da Pihole dann die Anfragen an dieFritz!Box senden würde, welche sie wiederum an Pihole senden würde. + Die Fritz!Box darf nicht als upstream DNS Server im Pi-hole eingestellt werden. Dies würde zu einem DNS Loop führen, da Pi-hole dann die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pi-hole senden würde. -Mit dieser Konfiguration sind im Pihole Dashboard keine individuellen Clients sichtbar. Für Pihole scheinen alle Anfragen von der Fritz!Box zu kommen. Dadurch können nicht alle Funktionen von Pihole genutzt werden, z.B. die Möglichkeit, Clients individuell zu filtern (Group Management). Wenn dies gewünscht ist, muss die Konfiguration #2 verwendet werden. +Mit dieser Konfiguration sind im Pi-hole Dashboard keine individuellen Clients sichtbar. Für Pi-hole scheinen alle Anfragen von der Fritz!Box zu kommen. Dadurch können nicht alle Funktionen von Pi-hole genutzt werden, z.B. die Möglichkeit, Clients individuell zu filtern (Group Management). Wenn dies gewünscht ist, muss die Konfiguration #2 verwendet werden. -## 2) Pihole als DNS Server via DHCP an Clients verteilen (LAN Seite) +## 2) Pi-hole als DNS Server via DHCP an Clients verteilen (LAN Seite) -Mit dieser Konfiguration wird allen Clients die IP des Pihole als DNS Server angeboten, wenn sie einen DHCP Lease vom der Fritz!Box anfordern. +Mit dieser Konfiguration wird allen Clients die IP des Pi-hole als DNS Server angeboten, wenn sie einen DHCP Lease vom der Fritz!Box anfordern. DNS Anfragen nehmen folgenden Weg ```bash -Client -> Pihole -> Upstream DNS Server +Client -> Pi-hole -> Upstream DNS Server ``` > Hinweis: Die Fritz!Box selbst wird den unter Internet/Zugangsdaten/DNS-Server eingestellten DNS Server nutzen. -Die Fritz!Box kann der Upstream Server von Pihole sein, solange Pihole nicht der Upstream Server der Fritz!Box ist. Dies würde zu einem DNS Loop führen. +Die Fritz!Box kann der Upstream Server von Pi-hole sein, solange Pi-hole nicht der Upstream Server der Fritz!Box ist. Dies würde zu einem DNS Loop führen. -Um diese Konfiguration zu nutzen, muss die IP des Pihole als "Lokaler DNS-Server" in +Um diese Konfiguration zu nutzen, muss die IP des Pi-hole als "Lokaler DNS-Server" in ```bash Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz @@ -56,20 +54,20 @@ eingetragen werden. >Hinweis: Clients bemerken Änderungen an den DHCP Einstellungen erst, wenn der DHCP Lease erneuert wird. Der einfachste Weg dies zu erzwingen ist ein Unterbrechen und Wiederherstellen der Netzwerkverbindung. -Nun sollen einzelne Clients in Piholes Dashboard auftrauchen. +Nun sollen einzelne Clients in Pi-hole Dashboard auftrauchen. ## 3) Kombination aus 1) und 2) -Durch die Kombination von 1) und 2) senden alle Clients und die Fritz!Box selbst DNS Anfragen direkt an Pihole. +Durch die Kombination von 1) und 2) senden alle Clients und die Fritz!Box selbst DNS Anfragen direkt an Pi-hole. ```bash -Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server +Client (incl. Fritz!Box) -> Pi-hole -> Upstream DNS Server ``` !!! warning - Die Fritz!Box darf nicht als Upstream DNS Server des Pihole gesetzt werden. Dies würde zu einem DNS Loop führen, da Pihole die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pihole weitergeben würde. + Die Fritz!Box darf nicht als Upstream DNS Server des Pi-hole gesetzt werden. Dies würde zu einem DNS Loop führen, da Pi-hole die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pi-hole weitergeben würde. -## Pihole im Gastnetzwerk nutzen +## Pi-hole im Gastnetzwerk nutzen Es gibt in der Fritz!Box keine Möglichkeit unter @@ -79,4 +77,4 @@ Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Gastnetz den DNS Server des Gastnetzwerks einzustellen. -Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pihole zu senden, muss der als Upstream DNS für die Fritz!Box (siehe #1) eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pihole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. +Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pi-hole zu senden, muss der als Upstream DNS für die Fritz!Box (siehe #1) eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pi-hole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. diff --git a/docs/routers/fritzbox.md b/docs/routers/fritzbox.md index c5477be9..a50aea09 100644 --- a/docs/routers/fritzbox.md +++ b/docs/routers/fritzbox.md @@ -1,20 +1,18 @@ -**This is an unsupported configuration created by the community** - -This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic prinicples to have a seemless DNS experience with Pihole and Fritz!Boxes . +This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic principles to have a seamless DNS experience with Pi-hole and Fritz!Boxes . > Note: There is no single way to do it right. Choose the one best fitting your needs. This guide is IPv4 only. You need to adjust for IPv6 accordingly -## 1) Using Pihole as upstream DNS server for your Fritz!Box +## 1) Using Pi-hole as upstream DNS server for your Fritz!Box -Using this configuration, Pihole is used for all devices within your network including the Fritz!Box itself. DNS requests are send in this order +Using this configuration, Pi-hole is used for all devices within your network including the Fritz!Box itself. DNS requests are sent in this order ```bash -Client -> Fritz!Box -> Pihole -> Upstream DNS Server +Client -> Fritz!Box -> Pi-hole -> Upstream DNS Server ``` -To set it up, enter Pihole's IP as "Preferred DNS server" **and** "Alternative DNS server" in +To set it up, enter Pi-hole's IP as "Preferred DNS server" **and** "Alternative DNS server" in ```bash Internet/Account Information/DNS server @@ -23,25 +21,25 @@ Internet/Account Information/DNS server ![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) !!! warning - Don't set the Fitz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole. + Don't set the Fitz!Box as upstrem DNS server for Pi-hole! This will lead to a DNS loop as the Pi-hole will send the queries to the Fritz!Box which in turn will send the to Pi-hole. -With this configuration, you won't see individual clients in pihole's dashboard. For pihole, all queries will appear as if they are comming from your Fritz!Box. You will therefore miss out some features, e.g. Group Management. This can be solved using method #2. +With this configuration, you won't see individual clients in Pi-hole's dashboard. For Pi-hole, all queries will appear as if they are coming from your Fritz!Box. You will therefore miss out on some features, e.g. Group Management. This can be solved using method #2. -## 2) Distribute Pihole as DNS server via DHCP +## 2) Distribute Pi-hole as DNS server via DHCP -Using this configuration, all clients will get Pihole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. -DNS requests are send in this order +Using this configuration, all clients will get Pi-hole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. +DNS requests are sent in this order ```bash -Client -> Pihole -> Upstream DNS Server +Client -> Pi-hole -> Upstream DNS Server ``` > Note: The Fritz!Box itself will use whatever is configured in Internet/Account Information/DNS server. -The Fritz!Box can be Pihole's upstream DNS server, as long Pihole itself is not the the upstream server for the Fritz!Box. This would cause a DNS loop. +The Fritz!Box can be Pi-hole's upstream DNS server, as long Pi-hole itself is not the upstream server for the Fritz!Box. This would cause a DNS loop. -To set it up, enter Pihole's IP as "Local DNS server" in +To set it up, enter Pi-hole's IP as "Local DNS server" in ```bash Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Network @@ -52,20 +50,20 @@ Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Networ >Note: Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. -You should see individual clients in Pihole's web dashboard. +You should see individual clients in Pi-hole's web dashboard. ## 3) Combining 1) and 2) -You can combine 1) and 2) which will let all clients send DNS requests to your Pihole **and** the Fritz!Box itself as well. +You can combine 1) and 2) which will let all clients send DNS requests to your Pi-hole **and** the Fritz!Box itself as well. ```bash -Client (incl. Fritz!Box) -> Pihole -> Upstream DNS Server +Client (incl. Fritz!Box) -> Pi-hole -> Upstream DNS Server ``` !!! warning - Don't set the Fritz!Box as upstrem DNS server for pihole! This will lead to a DNS loop as the Pihole will send the queries to the Fritz!Box which in turn will send the to Pihole + Don't set the Fritz!Box as upstrem DNS server for Pi-hole! This will lead to a DNS loop as the Pi-hole will send the queries to the Fritz!Box which in turn will send the to Pi-hole -## Using Pihole within the Guest Network +## Using Pi-hole within the Guest Network You may have noticed, that there is no option to set the DNS server for the guest network in @@ -73,4 +71,4 @@ You may have noticed, that there is no option to set the DNS server for the gues Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Guest Network ``` -The Fritz!Box always set its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pihole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. +The Fritz!Box always sets its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pi-hole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. From 38e115dcf3963b016de64200f10c19b7198b4afb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 9 Jan 2021 10:13:10 +0000 Subject: [PATCH 15/41] Bump linkinator from 2.8.0 to 2.13.0 Bumps [linkinator](https://github.com/JustinBeckwith/linkinator) from 2.8.0 to 2.13.0. - [Release notes](https://github.com/JustinBeckwith/linkinator/releases) - [Commits](https://github.com/JustinBeckwith/linkinator/compare/v2.8.0...v2.13.0) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 510 ++++++++++++++++------------------------------ package.json | 2 +- 2 files changed, 176 insertions(+), 336 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2d84fc7..c791baed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,18 +5,18 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", "dev": true }, "@babel/highlight": { @@ -129,12 +129,6 @@ "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", "dev": true }, - "@types/node": { - "version": "14.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.12.tgz", - "integrity": "sha512-ASH8OPHMNlkdjrEdmoILmzFfsJICvhBsFfAum4aKZ/9U4B6M6tTmTPh+f3ttWdD74CEGV5XvXWkbyfSdXaTd7g==", - "dev": true - }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -157,23 +151,6 @@ "dev": true, "requires": { "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "ansi-align": { @@ -299,6 +276,12 @@ "fill-range": "^7.0.1" } }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -359,27 +342,41 @@ } }, "cheerio": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", - "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "version": "1.0.0-rc.5", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", + "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", "dev": true, "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.1", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" + "cheerio-select-tmp": "^0.1.0", + "dom-serializer": "~1.2.0", + "domhandler": "^4.0.0", + "entities": "~2.1.0", + "htmlparser2": "^6.0.0", + "parse5": "^6.0.0", + "parse5-htmlparser2-tree-adapter": "^6.0.0" }, "dependencies": { "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true } } }, + "cheerio-select-tmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", + "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", + "dev": true, + "requires": { + "css-select": "^3.1.2", + "css-what": "^4.0.0", + "domelementtype": "^2.1.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.4" + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -436,6 +433,12 @@ "xdg-basedir": "^4.0.0" } }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -443,30 +446,31 @@ "dev": true }, "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", + "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", "dev": true, "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "boolbase": "^1.0.0", + "css-what": "^4.0.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.3", + "nth-check": "^2.0.0" } }, "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", + "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==", "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "2.1.2" } }, "decamelize": { @@ -514,18 +518,6 @@ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -536,46 +528,40 @@ } }, "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", + "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", "dev": true, "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - } + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" } }, "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", "dev": true }, "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", + "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", "dev": true, "requires": { - "domelementtype": "1" + "domelementtype": "^2.1.0" } }, "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz", + "integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0" } }, "dot-prop": { @@ -593,24 +579,12 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -641,24 +615,12 @@ "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", "dev": true }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -691,6 +653,15 @@ "picomatch": "^2.2.1" } }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "requires": { + "punycode": "^1.3.2" + } + }, "fastq": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", @@ -709,21 +680,6 @@ "to-regex-range": "^5.0.1" } }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -734,12 +690,6 @@ "path-exists": "^4.0.0" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -798,12 +748,12 @@ } }, "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", "dev": true, "requires": { - "ini": "^1.3.5" + "ini": "1.3.7" } }, "globby": { @@ -882,25 +832,15 @@ } }, "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz", + "integrity": "sha512-numTQtDZMoh78zJpaNdJ9MXb2cv5G3jwUoe3dMQODubZvLoGvTE/Ofp6sHvH8OGKcN/8A47pGLi/k58xHP/Tfw==", "dev": true, "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - } + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.4.4", + "entities": "^2.0.0" } }, "http-cache-semantics": { @@ -909,19 +849,6 @@ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", "dev": true }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -930,23 +857,6 @@ "requires": { "agent-base": "6", "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "ignore": { @@ -1117,9 +1027,9 @@ "dev": true }, "jsonexport": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonexport/-/jsonexport-3.0.1.tgz", - "integrity": "sha512-lxDoAZxmWDt1wa4S75CUYe/ZASdmOYyhV7iYbF4npTWxrDv19ofZpJMGbt20W5Orx0hYuid65zGHpt6rRW0Z3A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonexport/-/jsonexport-3.1.0.tgz", + "integrity": "sha512-QekAMWAZZN263aDbA5J06U+dCwRxS+L4vCYGh5pbnI0pw4T2A0RaDWE9APOPcxvGsQcjUvfHiywvnTo/n5Bzcg==", "dev": true }, "keyv": { @@ -1162,21 +1072,20 @@ } }, "linkinator": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/linkinator/-/linkinator-2.8.0.tgz", - "integrity": "sha512-v8MtGeoJT+6RTSEKkB1IPKbv49Esmp5m0o2b4mLzULJ8oX5GFI9OPjMT4ftQ7guhQ/hLy5iDnpoE95t6gB8Plg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/linkinator/-/linkinator-2.13.0.tgz", + "integrity": "sha512-CSktxDpKO80fPs89x/lv8fsUv5fAljvp2kIIF+bbMG6ZN/T02K6KUlsuGm+lK1eJfcKtaopji0dPOFmRvbssmA==", "dev": true, "requires": { "chalk": "^4.0.0", - "cheerio": "^1.0.0-rc.2", - "finalhandler": "^1.1.2", + "cheerio": "^1.0.0-rc.5", "gaxios": "^4.0.0", "glob": "^7.1.6", "jsonexport": "^3.0.0", "marked": "^1.2.5", "meow": "^8.0.0", "p-queue": "^6.2.1", - "serve-static": "^1.14.1", + "serve-handler": "^6.1.3", "server-destroy": "^1.0.1", "update-notifier": "^5.0.0" } @@ -1190,12 +1099,6 @@ "p-locate": "^4.1.0" } }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -1292,9 +1195,9 @@ "dev": true }, "marked": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.6.tgz", - "integrity": "sha512-7vVuSEZ8g/HH3hK/BH/+7u/NJj7x9VY4EHzujLDcqAQLiOUeFJYAsfSAyoWtR17lKrx7b08qyIno4lffwrzTaA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.7.tgz", + "integrity": "sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA==", "dev": true }, "mdurl": { @@ -1304,9 +1207,9 @@ "dev": true }, "meow": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz", - "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -1338,12 +1241,21 @@ "picomatch": "^2.0.5" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "dev": true }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -1383,9 +1295,9 @@ } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node-fetch": { @@ -1413,21 +1325,12 @@ "dev": true }, "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", "dev": true, "requires": { - "boolbase": "~1.0.0" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" + "boolbase": "^1.0.0" } }, "once": { @@ -1527,20 +1430,20 @@ } }, "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "dev": true, "requires": { - "@types/node": "*" + "parse5": "^6.0.1" } }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1553,12 +1456,24 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -1587,6 +1502,12 @@ "once": "^1.3.1" } }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, "pupa": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", @@ -1603,9 +1524,9 @@ "dev": true }, "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, "rc": { @@ -1683,17 +1604,6 @@ } } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -1753,12 +1663,6 @@ "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", "dev": true }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", @@ -1785,45 +1689,20 @@ } } }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", "dev": true, "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" } }, "server-destroy": { @@ -1832,12 +1711,6 @@ "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", "dev": true }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -1888,12 +1761,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -1934,15 +1801,6 @@ } } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -1997,12 +1855,6 @@ "is-number": "^7.0.0" } }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, "trim-newlines": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", @@ -2039,12 +1891,6 @@ "crypto-random-string": "^2.0.0" } }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "update-notifier": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.0.1.tgz", @@ -2076,12 +1922,6 @@ "prepend-http": "^2.0.0" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index 5f7d8772..86360043 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "test": "npm run markdownlint && npm run linkinator" }, "devDependencies": { - "linkinator": "^2.8.0", + "linkinator": "^2.13.0", "markdownlint-cli2": "0.0.11" } } From 9bd7fa9861c3850c8ddc491c8ef4b85dc1c48b53 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 9 Jan 2021 11:17:20 +0000 Subject: [PATCH 16/41] Bump markdownlint-cli2 from 0.0.11 to 0.0.13 Bumps [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) from 0.0.11 to 0.0.13. - [Release notes](https://github.com/DavidAnson/markdownlint-cli2/releases) - [Commits](https://github.com/DavidAnson/markdownlint-cli2/compare/v0.0.11...v0.0.13) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 91 +++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 42 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index c791baed..a93e1249 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,28 +83,28 @@ } }, "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", + "@nodelib/fs.stat": "2.0.4", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", + "@nodelib/fs.scandir": "2.1.4", "fastq": "^1.6.0" } }, @@ -191,13 +191,10 @@ } }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "array-union": { "version": "2.1.0", @@ -663,9 +660,9 @@ } }, "fastq": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", - "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", + "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -757,9 +754,9 @@ } }, "globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -1138,12 +1135,12 @@ "dev": true }, "markdown-it": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.0.tgz", - "integrity": "sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.2.tgz", + "integrity": "sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA==", "dev": true, "requires": { - "argparse": "^1.0.7", + "argparse": "^2.0.1", "entities": "~2.0.0", "linkify-it": "^3.0.1", "mdurl": "^1.0.1", @@ -1151,24 +1148,24 @@ } }, "markdownlint": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.21.1.tgz", - "integrity": "sha512-8kc88w5dyEzlmOWIElp8J17qBgzouOQfJ0LhCcpBFrwgyYK6JTKvILsk4FCEkiNqHkTxwxopT2RS2DYb/10qqg==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.22.0.tgz", + "integrity": "sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w==", "dev": true, "requires": { - "markdown-it": "11.0.0" + "markdown-it": "12.0.2" } }, "markdownlint-cli2": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.0.11.tgz", - "integrity": "sha512-+dwVrLo2sisB8OJE8vdT+gTQCOuaYFJsYKKfh1fnkHedSMxVrX6XMID5kUKI7iSq6GICugPnS5kjjVwCbe01vg==", + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.0.13.tgz", + "integrity": "sha512-Fg4bIf70vPW9CHHBE6wkL5TYwOF/bQ7XQ+VGXLws5TTgP8voaeVmF085TkyWYOSippWRU+Ify1VkMw1S0VlbwA==", "dev": true, "requires": { "globby": "~11.0.1", - "markdownlint": "~0.21.1", - "markdownlint-cli2-formatter-default": "~0.0.1", - "markdownlint-rule-helpers": "~0.12.0", + "markdownlint": "~0.22.0", + "markdownlint-cli2-formatter-default": "~0.0.2", + "markdownlint-rule-helpers": "~0.13.0", "micromatch": "~4.0.2", "strip-json-comments": "~3.1.1", "yaml": "~1.10.0" @@ -1183,15 +1180,15 @@ } }, "markdownlint-cli2-formatter-default": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.1.tgz", - "integrity": "sha512-JvWhlus5zR4cFywXB2RSPVX73YD9177xm9WkV/8CRPDS1MM/Fh6Ds0WnY67ZaiITavZ0H+Fgz1aVhUwrPNa7ug==", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.2.tgz", + "integrity": "sha512-jIz1X3SIC8sX4NDFqQFUXL+JEtfnDoN4i+xocEu+etcxGX455pHb6sx86f/yVk4mKJ2o7aNe2ydSx9an22BfBg==", "dev": true }, "markdownlint-rule-helpers": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.12.0.tgz", - "integrity": "sha512-Q7qfAk+AJvx82ZY52OByC4yjoQYryOZt6D8TKrZJIwCfhZvcj8vCQNuwDqILushtDBTvGFmUPq+uhOb1KIMi6A==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.13.0.tgz", + "integrity": "sha512-rRY0itbcHG4e+ntz0bbY3AIceSJMKS0TafEMgEtKVHRZ54/JUSy6/4ypCL618RlJvYRej+xMLxX5nkJqIeTZaQ==", "dev": true }, "marked": { @@ -1755,12 +1752,6 @@ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", diff --git a/package.json b/package.json index 86360043..a45d561e 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,6 @@ }, "devDependencies": { "linkinator": "^2.13.0", - "markdownlint-cli2": "0.0.11" + "markdownlint-cli2": "0.0.13" } } From 835281e421883a09269952efc8cbb0ea8e83fbb9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 9 Jan 2021 12:16:53 +0000 Subject: [PATCH 17/41] Bump mkdocs-material from 6.1.6 to 6.2.3 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 6.1.6 to 6.2.3. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/docs/changelog.md) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/6.1.6...6.2.3) Signed-off-by: dependabot-preview[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 08379ab2..10146208 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ markdown-include==0.6.0 mkdocs==1.1.2 mkdocs-git-revision-date-localized-plugin==0.8 -mkdocs-material==6.1.6 +mkdocs-material==6.2.3 mkdocs-redirects==1.0.1 From 49482464a9ecf9964eae35c4a2e8d52afbd939c2 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sun, 10 Jan 2021 20:54:04 +0100 Subject: [PATCH 18/41] Rewrote German guide and added section about conditional forwarding Signed-off-by: yubiuser --- docs/images/conditional-forwarding.png | Bin 0 -> 5751 bytes docs/routers/fritzbox-de.md | 80 +++++++++++++------------ 2 files changed, 43 insertions(+), 37 deletions(-) create mode 100644 docs/images/conditional-forwarding.png diff --git a/docs/images/conditional-forwarding.png b/docs/images/conditional-forwarding.png new file mode 100644 index 0000000000000000000000000000000000000000..27e7eeb2aebe413525aa77be4724419f88376e96 GIT binary patch literal 5751 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 Fritz!Box -> Pi-hole -> Upstream DNS Server -``` - -Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in - -```bash -Internet/Zugangsdaten/DNS-Server -``` - -![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) - -eingetragen werden. - -!!! warning - Die Fritz!Box darf nicht als upstream DNS Server im Pi-hole eingestellt werden. Dies würde zu einem DNS Loop führen, da Pi-hole dann die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pi-hole senden würde. - -Mit dieser Konfiguration sind im Pi-hole Dashboard keine individuellen Clients sichtbar. Für Pi-hole scheinen alle Anfragen von der Fritz!Box zu kommen. Dadurch können nicht alle Funktionen von Pi-hole genutzt werden, z.B. die Möglichkeit, Clients individuell zu filtern (Group Management). Wenn dies gewünscht ist, muss die Konfiguration #2 verwendet werden. - - -## 2) Pi-hole als DNS Server via DHCP an Clients verteilen (LAN Seite) - -Mit dieser Konfiguration wird allen Clients die IP des Pi-hole als DNS Server angeboten, wenn sie einen DHCP Lease vom der Fritz!Box anfordern. +Mit dieser Konfiguration wird allen Clients die IP des Pi-hole als DNS Server angeboten, wenn sie einen DHCP Lease von der Fritz!Box anfordern. DNS Anfragen nehmen folgenden Weg ```bash @@ -38,7 +14,7 @@ Client -> Pi-hole -> Upstream DNS Server ``` > Hinweis: -Die Fritz!Box selbst wird den unter Internet/Zugangsdaten/DNS-Server eingestellten DNS Server nutzen. +Die Fritz!Box selbst wird den unter Internet/Zugangsdaten/DNS-Server eingestellten DNS Server nutzen (siehe unten). Die Fritz!Box kann der Upstream Server von Pi-hole sein, solange Pi-hole nicht der Upstream Server der Fritz!Box ist. Dies würde zu einem DNS Loop führen. Um diese Konfiguration zu nutzen, muss die IP des Pi-hole als "Lokaler DNS-Server" in @@ -47,27 +23,39 @@ Um diese Konfiguration zu nutzen, muss die IP des Pi-hole als "Lokaler DNS-Serve Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz ``` -![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) - eingetragen werden. +![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-dhcp-de.png) + >Hinweis: Clients bemerken Änderungen an den DHCP Einstellungen erst, wenn der DHCP Lease erneuert wird. Der einfachste Weg dies zu erzwingen ist ein Unterbrechen und Wiederherstellen der Netzwerkverbindung. -Nun sollen einzelne Clients in Pi-hole Dashboard auftrauchen. +Nun sollten einzelne Clients in Pi-hole Dashboard auftrauchen. -## 3) Kombination aus 1) und 2) +## Pi-hole als Upstream DNS Server der Fritz!Box (WAN Seite) -Durch die Kombination von 1) und 2) senden alle Clients und die Fritz!Box selbst DNS Anfragen direkt an Pi-hole. +Mit dieser Konfiguration wird Pi-hole auch von der Fritz!Box selbst als Upstream DNS Server genutzt. DNS Anfragen nehmen folgenden Weg ```bash -Client (incl. Fritz!Box) -> Pi-hole -> Upstream DNS Server +(Clients) -> Fritz!Box -> Pi-hole -> Upstream DNS Server ``` -!!! warning - Die Fritz!Box darf nicht als Upstream DNS Server des Pi-hole gesetzt werden. Dies würde zu einem DNS Loop führen, da Pi-hole die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pi-hole weitergeben würde. +Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in -## Pi-hole im Gastnetzwerk nutzen +```bash +Internet/Zugangsdaten/DNS-Server +``` + +eingetragen werden. + +![Screenshot der Fritz!Box WAN DNS Konfiguration](../images/fritzbox-wan-dns-de.png) + +!!! warning + Die Fritz!Box darf mit dieser Konfiguration nicht als Upstream DNS Server im Pi-hole eingestellt werden. Dies würde zu einem DNS Loop führen, da Pi-hole dann die Anfragen an die Fritz!Box senden würde, welche sie wiederum an Pi-hole senden würde. + +Wird ausschließlich diese Konfiguration genutz, sind im Pi-hole Dashboard keine individuellen Clients sichtbar. Für Pi-hole scheinen alle Anfragen von der Fritz!Box zu kommen. Dadurch können nicht alle Funktionen von Pi-hole genutzt werden, z.B. die Möglichkeit, Clients individuell zu filtern (Group Management). Wenn dies gewünscht ist, muss Pi-hole (zusätzlich) als DNS Server via DHCP an die Clients verteilt werden (siehe oben). + +### Pi-hole im Gastnetzwerk nutzen Es gibt in der Fritz!Box keine Möglichkeit unter @@ -77,4 +65,22 @@ Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Gastnetz den DNS Server des Gastnetzwerks einzustellen. -Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pi-hole zu senden, muss der als Upstream DNS für die Fritz!Box (siehe #1) eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pi-hole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. +Die Fritz!Box wird immer ihre eigene IP als DNS Server des Gastnetzes einstellen. Um die DNS Anfragen dennoch über den Pi-hole zu senden, muss dieser als Upstream DNS Server für die Fritz!Box eingetragen werden. Da es keine andere Option gibt, werden alle Anfragen aus dem Gastnetz für Pi-hole so erscheinen, als ob sie direkt von der Fritz!Box kommen. Eine individuelle Filterung je nach Client innerhalb des Gastnetzwerks ist deshalb nicht möglich. + +## Hostnamen in Pi-hole statt IP-Addressen - Conditional forwarding + +Wenn die Fritz!Box im Netzwerk als DHCP Server fungiert, werden die Hostnamen der Clients nur dort registriert. Pi-hole versucht standardmäßig, die IP-Adressen der Clients wieder in Hostnamen aufzulösen. Daher müssen die Anfragen zur Fritz!Box gelangen. +Dafür gibt es zwei Wege: + +* Die Fritz!Box ist der Upstream DNS Server des Pi-holes. Damit landen alle Anfragen sowieso bei der Fritz!Box, welche die Hostnamen an Pi-hole zurücksenden kann. + +!!! warning + Die Fritz!Box darf nur der Upstream DNS Server des Pi-hole sein, wenn dieser nicht gleichzeitig der Upstream DNS Server der Fritz!Box ist. Dies würde zu einem DNS Loop führen. + +* Es werden nur die Anfragen an die Fritz!Box gesendet, welche versuchen im lokalen Netzwerk IP-Adressen wieder Hostnamen zuzuordnene. Alle anderen Anfragen werden an den Upstream DNS Server des Pi-Hole gesendet. Dafür ist die Option *Conditional forwarding* zuständig. +Folgende Einstellungen müssen dafür vorgenommen werden: + * **Local network in CIDR notation:** IP-Bereich des Netzwerks in CIDR Notation, Standard für die Fritz!Box ist **192.168.178.0/24** + * **IP address of your DHCP server (router):** IP-Adresse der Fritz!Box selbst, Standard ist **192.168.178.1** + * **Local domain name (optional):** Name der lokalen Domän, für die Fritz!Box **fritz.box** + +![Screenshot der Conditional Forwarding Einstellungen](../images/conditional-forwarding.png) From f2224ca9b9b99e520beca3abb7150054f12cb65e Mon Sep 17 00:00:00 2001 From: yubiuser Date: Tue, 12 Jan 2021 20:59:48 +0100 Subject: [PATCH 19/41] Add section about the need to activate advanced view Signed-off-by: yubiuser --- docs/images/fritzbox-advanced-de.png | Bin 0 -> 5203 bytes docs/routers/fritzbox-de.md | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 docs/images/fritzbox-advanced-de.png diff --git a/docs/images/fritzbox-advanced-de.png b/docs/images/fritzbox-advanced-de.png new file mode 100644 index 0000000000000000000000000000000000000000..de6b62c4b68bdb8d1c9f07966edb99fea00a1560 GIT binary patch literal 5203 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 Date: Wed, 13 Jan 2021 20:51:06 +0100 Subject: [PATCH 20/41] Rewrote English guide in one flow, added info about advances settings and conditional forwarding Signed-off-by: yubiuser --- docs/images/fritzbox-advanced.png | Bin 0 -> 3967 bytes docs/routers/fritzbox-de.md | 2 +- docs/routers/fritzbox.md | 82 +++++++++++++++++------------- 3 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 docs/images/fritzbox-advanced.png diff --git a/docs/images/fritzbox-advanced.png b/docs/images/fritzbox-advanced.png new file mode 100644 index 0000000000000000000000000000000000000000..d0891574a319132fb9413fbb0cc71ee9ca0427e1 GIT binary patch literal 3967 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 Fritz!Box -> Pi-hole -> Upstream DNS Server ``` -Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNS-Server" **und** "Alternativer DNS-Server" in +Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNSv4-Server" **und** "Alternativer DNSv4-Server" in ```bash Internet/Zugangsdaten/DNS-Server diff --git a/docs/routers/fritzbox.md b/docs/routers/fritzbox.md index a50aea09..65093d42 100644 --- a/docs/routers/fritzbox.md +++ b/docs/routers/fritzbox.md @@ -1,43 +1,27 @@ -This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic principles to have a seamless DNS experience with Pi-hole and Fritz!Boxes . +This guide was developed using FRITZ!OS 07.21 but should work for others too. It aims to line out a few basic principles to have a seamless DNS experience with Pi-hole and Fritz!Boxes. > Note: There is no single way to do it right. Choose the one best fitting your needs. -This guide is IPv4 only. You need to adjust for IPv6 accordingly +This guide is IPv4 only. You need to adjust for IPv6 accordingly. -## 1) Using Pi-hole as upstream DNS server for your Fritz!Box +### Enable advanced settings -Using this configuration, Pi-hole is used for all devices within your network including the Fritz!Box itself. DNS requests are sent in this order +Some of the the follwowing settings might be visible only if advanced settings are enabled. Therefore, "View" has to be changed to advanced by clicking on "Standard" in the lower left corner. -```bash -Client -> Fritz!Box -> Pi-hole -> Upstream DNS Server -``` +![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-advanced.png) -To set it up, enter Pi-hole's IP as "Preferred DNS server" **and** "Alternative DNS server" in - -```bash -Internet/Account Information/DNS server -``` - -![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) - -!!! warning - Don't set the Fitz!Box as upstrem DNS server for Pi-hole! This will lead to a DNS loop as the Pi-hole will send the queries to the Fritz!Box which in turn will send the to Pi-hole. - -With this configuration, you won't see individual clients in Pi-hole's dashboard. For Pi-hole, all queries will appear as if they are coming from your Fritz!Box. You will therefore miss out on some features, e.g. Group Management. This can be solved using method #2. - - -## 2) Distribute Pi-hole as DNS server via DHCP +## Distribute Pi-hole as DNS server via DHCP Using this configuration, all clients will get Pi-hole's IP offered as DNS server when they request a DHCP lease from your Fritz!Box. -DNS requests are sent in this order +DNS queries take the following path ```bash Client -> Pi-hole -> Upstream DNS Server ``` > Note: -The Fritz!Box itself will use whatever is configured in Internet/Account Information/DNS server. -The Fritz!Box can be Pi-hole's upstream DNS server, as long Pi-hole itself is not the upstream server for the Fritz!Box. This would cause a DNS loop. +The Fritz!Box itself will use whatever is configured in Internet/Account Information/DNS server (see below). +The Fritz!Box can be Pi-hole's upstream DNS server, as long Pi-hole itself is not the upstream server of the Fritz!Box. This would cause a DNS loop. To set it up, enter Pi-hole's IP as "Local DNS server" in @@ -48,27 +32,57 @@ Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Home Networ ![Screenshot of Fritz!Box DHCP Settings](../images/fritzbox-dhcp.png) >Note: -Clients will notice changes in DHCP settings only after they acquire a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. +Clients will notice changes in DHCP settings only after they acquired a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network. -You should see individual clients in Pi-hole's web dashboard. +Now you should see individual clients in Pi-hole's web dashboard. -## 3) Combining 1) and 2) -You can combine 1) and 2) which will let all clients send DNS requests to your Pi-hole **and** the Fritz!Box itself as well. +## Pi-hole as upstream DNS server for your Fritz!Box + +With this configuration, Pi-hole is also used by the Fritz!Box itself as an upstream DNS server. DNS queries take the following path ```bash -Client (incl. Fritz!Box) -> Pi-hole -> Upstream DNS Server +(Clients) -> Fritz!Box -> Pi-hole -> Upstream DNS Server ``` +To set it up, enter Pi-hole's IP as "Preferred DNSv4 server" **and** "Alternative DNSv4 server" in + +```bash +Internet/Account Information/DNS server +``` + +![Screenshot of Fritz!Box WAN DNS Configuration](../images/fritzbox-wan-dns.png) + !!! warning - Don't set the Fritz!Box as upstrem DNS server for Pi-hole! This will lead to a DNS loop as the Pi-hole will send the queries to the Fritz!Box which in turn will send the to Pi-hole + Don't set the Fitz!Box as upstrem DNS server for Pi-hole if using this configuration! This will lead to a DNS loop as the Pi-hole will send the queries to the Fritz!Box which in turn will send them to Pi-hole. -## Using Pi-hole within the Guest Network +If only this configuration is used, you won't see individual clients in Pi-hole's dashboard. For Pi-hole, all queries will appear as if they are coming from your Fritz!Box. You will therefore miss out on some features, e.g. Group Management. If you want to use them, Pi-hole must (additionally) be distributed to the clients as DNS server via DHCP (see above). -You may have noticed, that there is no option to set the DNS server for the guest network in +### Using Pi-hole within the Guest Network + +There is no option to set the DNS server for the guest network in ```bash Home Network/Network/Network Settings/IP Adresses/IPv4 Configuration/Guest Network ``` -The Fritz!Box always sets its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pi-hole as upstream DNS server for your Fritz!Box (see #1). As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. +The Fritz!Box always sets its own IP as DNS server for the guest network. To filter its traffic, you have to setup Pi-hole as upstream DNS server for your Fritz!Box. As there is no other option, all DNS requests from your guest network will appear as coming from your Fritz!Box. Individual filtering per client within the guest network is therefore not possible. + +## Hostnames instead of IP addresses in Pi-hole's web interface - Conditional forwarding + +In case the Fritz!Box is used as DHCP server, client's hostames are registered only there. By default, Pi-hole tries to resolve the IP addresses of the clients back into host names. Therefore, the requests must reach the Fritz!Box. +There are two ways to do this: + +* The Fritz!Box is the upstream DNS server of the Pi-hole. This means that all queries end up with the Fritz!Box anyway, which can send the host names back to Pi-hole. + +!!! warning + The Fritz!Box may only be the upstream DNS server of the Pi-hole if Pi-hole is not the upstream DNS server of the Fritz!Box. This would lead to a DNS loop. + +* Only those queries are sent to the Fritz!Box that attempt to determine hostnames for IP addresses (clients) of the local network. All other requests are sent to the upstream DNS server of the Pi-Hole. The *Conditional forwarding* option is responsible for this. +The following settings must be made: + * **Local network in CIDR notation:** Standard IP range of the Fritz!Box is **192.168.178.0/24** + * **IP address of your DHCP server (router):** IP of the Fritz!Box, standard is **192.168.178.1** + * **Local domain name (optional):** Fritz!Box uses **fritz.box** + +![Screenshot der Conditional Forwarding Einstellungen](../images/conditional-forwarding.png) + From ea28e2efbade1c47028f3ae1ada90f892ad01f78 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 30 Aug 2020 15:20:20 +0200 Subject: [PATCH 21/41] Add WireGuard guide Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 111 ++++++++++++++++++++++ docs/guides/wireguard/concept.md | 32 +++++++ docs/guides/wireguard/faq.md | 85 +++++++++++++++++ docs/guides/wireguard/internal.md | 71 ++++++++++++++ docs/guides/wireguard/overview.md | 30 ++++++ docs/guides/wireguard/route-everything.md | 13 +++ docs/guides/wireguard/server.md | 110 +++++++++++++++++++++ mkdocs.yml | 9 ++ 8 files changed, 461 insertions(+) create mode 100644 docs/guides/wireguard/client.md create mode 100644 docs/guides/wireguard/concept.md create mode 100644 docs/guides/wireguard/faq.md create mode 100644 docs/guides/wireguard/internal.md create mode 100644 docs/guides/wireguard/overview.md create mode 100644 docs/guides/wireguard/route-everything.md create mode 100644 docs/guides/wireguard/server.md diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md new file mode 100644 index 00000000..359cb2fb --- /dev/null +++ b/docs/guides/wireguard/client.md @@ -0,0 +1,111 @@ +# Adding a WireGuard client + +Adding clients is really simple and easy. The process for setting up a client is similar to setting up the server. This is expected as WireGuard's concept is more of the type Peer-to-Peer than server-client as mentioned at the very beginning of the [Server configuration](server.md). + +For each new client, the following steps must be taken. For the sake of simplicity, we will create the config file on the server itself. This, however, means that you need to transfer the config file *securely* to your server as it contains the private key of your client. An alternative way of doing this is to generate the configuration locally on your client and add the necessary lines to your server's configuration. + +## Key generation + +We generate a key-pair for the client `NAME` (replace accordingly everywhere below): + +``` bash +sudo -i +cd /etc/wireguard +umask 077 +wg genkey | tee NAME.key | wg pubkey > NAME.pub +``` + +## PSK Key generation + +We furthermore recommend generating a pre-shared key (PSK) in addition to the keys above. This adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography and is mainly for post-quantum resistance. A pre-shared key should be generated for each peer pair and *should not be reused*. + +``` bash +wg genpsk > NAME.psk +``` + +## Add client to server configuration + +Add the following to your `/etc/wireguard/wg0.conf`: + +``` toml +[Peer] +Address = 10.100.0.2/24 # Replace this IP address for subsequent clients +AllowedIPs = 10.100.0.1/32 # This client is only allowed to talk to the server +``` + +Then run + +``` bash +echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf +echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf +``` + +to copy the clients's public and pre-shared keys into the server's config file. + +## Create client configuration + +Create a dedicated config file for your new client: + +``` bash +nano NAME.conf +``` + +with the content + +``` toml +[Interface] +Address = 10.100.0.2/24 # Replace this IP address for subsequent clients +DNS = 10.100.0.1 # IP address of your Pi-hole +Domains = ~. # Enforce all DNS over the WireGuard connection +``` + +``` bash +echo "PrivateKey = $(cat NAME.key)" >> NAME.conf +``` + +Then add your server as the only peer for this client: + +``` toml +[Peer] +AllowedIPs = 10.0.0.1/24 +Endpoint = [your public IP or domain]:44711 +PersistentKeepalive = 25 +``` + +Make sure that each IP is used only once. + + +??? info "About the `PersistentKeepalive` setting" + By default WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). + + When a peer is behind NAT or a firewall, it typically wants to be able to receive incoming packets even when it is not sending any packets itself. Because NAT and stateful firewalls keep track of "connections", if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called *persistent keepalives*. + + When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is `25` seconds. Setting it to 0 turns the feature off, which is the default. + + **TL;DR** If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the "connection" open in the eyes of NAT. + + +Then add the public key of the server as well as the PSK for this connection: + +``` bash +echo "PublicKey = $(cat server.pub)" >> NAME.conf +echo "PresharedKey = $(cat NAME.psk)" >> NAME.conf +``` + +That's it. + +## Copy config file to client + +You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: + +``` bash +qrencode -t ansiutf8 -r NAME.conf +``` + +(you may need to install `qrencode` using `sudo apt-get install qrencode`) + +## Connect to your WireGuard VPN + +After creating/copying the connection information over to your client, you may use the client you prefer to connect to your system. Mind that setting up auto-start of the WireGuard connection may lead to issues if you are doing this too early (when the system cannot resolve DNS). See our [FAQ](faq.md) for further hints. + +{!abbreviations.md!} diff --git a/docs/guides/wireguard/concept.md b/docs/guides/wireguard/concept.md new file mode 100644 index 00000000..9edcdf6d --- /dev/null +++ b/docs/guides/wireguard/concept.md @@ -0,0 +1,32 @@ +# Conceptual overview + +Before we get started with installing a `wireguard` server, we'll quickly give a general conceptual overview of what WireGuard is about. You can skip this section if you already know what is going on under the hood or don't care (and just want to have it running). + +WireGuard securely encapsulates IP packets over UDP. You add a WireGuard interface, configure it with your private key and your peers' public keys, and then you send packets across it. + +WireGuard works by adding a network interface, like `eth0` or `wlan0`, called `wg0` (or `wg1`, +`wg2`, `wg3`, etc). This interface acts as a tunnel interface. Routes for this network interface will be added automatically based on the configuration file you will learn about below. All aspects of this virtual interface will be configured automatically by the `wg-tools`. + +WireGuard associates tunnel IP addresses with public keys and remote endpoints. When the interface +**sends a packet to a peer**, it does the following: + +1. This packet is meant for `192.168.30.8`. Is this peer configured? + 1. Yes: peer `adams-laptop`. Continue with step 2. + 2. No: Not for any configured peer, drop the packet and end here. + +2. Encrypt the IP packet using peer `adams-laptop`'s public key. +3. What is the remote endpoint of peer `adams-laptop`? Let me look... Okay, the endpoint is host `216.58.211.110:53133` (UDP). +4. Send encrypted data over the Internet to this host. + +When the interface **receives a packet from a peer**, this happens: + +1. Received a packet from host `98.139.183.24:7361`. Let's decrypt it! +2. It decrypted and authenticated properly for peer `evas-android`. Okay, let's remember that peer +`evas-android`'s most recent Internet endpoint is `98.139.183.24:7361` (UDP). +3. Once decrypted, the plain-text packet is from `192.168.43.89`. Is peer `evas-android` allowed to be sending us packets as 192.168.43.89? + 1. Yes: accept the packet on the interface and process it (forwarding to further local client, into the Internet, etc.) + 2. No: drop it. + +Behind the scenes there is much happening to provide proper privacy, authenticity, and perfect forward secrecy, using state-of-the-art cryptography. + +If you're interested in the internal inner workings, you might be interested in reading through the various articles on their official website [www.wireguard.com](https://www.wireguard.com) which is also where we took the vast majority of content in this guide from. diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md new file mode 100644 index 00000000..e92e3ecd --- /dev/null +++ b/docs/guides/wireguard/faq.md @@ -0,0 +1,85 @@ +# Frequently asked questions + +## Issues with dynamic server IP + +Host names cannot be resolved during startup. This may lead to a five minutes delay during boot. A solution to this is to disable the automatic start of the `wg` interface during start and connect only later (manually) when you are sure that you can resolve host names. + +1. Disable `auto wg0` in `/etc/network/interfaces` (put `#` in front, like `#auto wg0`) +2. Start `wireguard` manually using `sudo ifup wg0` + +If the IP changes while the connection is running, resolving the new IP address fails otten. Reconnect using + +``` bash +sudo ifdown wg0 && sudo ifup wg0 +``` + +To achieve a permanent solution, one can install a `cron` job which restarts the connection automatically whenever a change is detected. This avoids excessive restarts of the interface. Example script (taken from [Ubuntuusers Wiki](https://wiki.ubuntuusers.de/WireGuard)): + +``` bash +#!/bin/bash +# Check state of wg0 interface +wgstatus=$(wg) +if [ "$wgstatus" == "interface: wg0" ]; then + ip link delete wg0 && ifup wg0 +elif [ "$wgstatus" == "interface: wg0" ]; then + ifup wg0 +else + file="/tmp/digIP.txt" + digIP=$(dig +short beispiel2.domain.de) # Change this to your domain ! + if [ -e "$file" ]; then + fileTXT=$(cat "$file") + if [ "$digIP" != "$fileTXT" ]; then + #echo "Daten sind gleich" + /sbin/ifdown wg0 + /sbin/ifup wg0 + echo "$digIP" > "$file" + fi + else + echo "$digIP" > "$file" + fi +fi +``` + +Store this file as `/home/[user name]/wg-restart.sh` and add it to your `crontab`: + +``` bash +sudo crontab -e +``` + +``` plain +*/10 * * * * bash /home/[user name]/wg-restart.sh # Runs the script every 10 minutes +``` + +## Routes are periodically reset + +Users of NetworkManager should make sure that it is not managing the WireGuard interface(s). For example, create the configuration file `/etc/NetworkManager/conf.d/unmanaged.conf` with content + +``` toml +[keyfile] +unmanaged-devices=interface-name:wg* +``` + +[source](https://wiki.archlinux.org/index.php/WireGuard) + +## Broken DNS resolution + +When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon new connection. This could be caused by a network manager or DHCP client overwriting `/etc/resolv.conf`. +By default, `wg-quick` uses `resolvconf` to register new DNS entries (from the DNS keyword in the configuration file). This will cause issues with network managers and DHCP clients that do not use `resolvconf`, as they will overwrite `/etc/resolv.conf` thus removing the DNS servers added by `wg-quick`. + +The solution is to use networking software that supports `resolvconf`. + +!!! info "Hint for Ubuntu users" + Users of `systemd-resolved` should make sure that `systemd-resolvconf` is installed. + +[source](https://wiki.archlinux.org/index.php/WireGuard) + +## Low MTU + +Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client: + +``` toml +[Interface] +MTU = 1500 +``` + +[source](https://wiki.archlinux.org/index.php/WireGuard) diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md new file mode 100644 index 00000000..2405b655 --- /dev/null +++ b/docs/guides/wireguard/internal.md @@ -0,0 +1,71 @@ +# Access devices in the internal network through the WireGuard tunnel + +## Enable IP forwarding on the server + +Enable IP forwarding on your server by removing the comments in front of + +``` toml +net.ipv4.ip_forward = 1 +net.ipv6.conf.all.forwarding = 1 +``` + +in the file `/etc/sysctl.d/99-sysctl.conf` + +Then apply the new option with the command below. + +``` bash +sudo sysctl -p +``` + +If you see the options repeated like + +``` plain +net.ipv4.ip_forward=1 +``` + +they were enabled successfully. + +A properly configured firewall is ***highly*** recommended for any Internet-facing device. Configuring a firewall (`iptables`, `ufw`, etc.) is not part of this guide. + +## Enable NAT on the server + +!!! info "Optional for NAT" + If the server is behind a router and receives traffic via NAT, these iptables rules are not needed. + +On your server, add the following to the `[INTERFACE]` section: + +``` toml +PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE +``` + +!!! warning "Substitute interface" + Substitute `eth0` in the preceding lines to match the Internet-facing interface. + +??? info "The `PostUp` and `PostDown` options" + `PostUp` and `PostDown` defines steps to be run after the interface is turned on or off, respectively. In this case, iptables is used to set Linux IP masquerade rules to allow all the clients to share the server’s IPv4 and IPv6 address. + The rules will then be cleared once the tunnel is down. + +## Allow clients to access other devices + +In our standard configuration, we have configured the clients in such a way that they can only speak to the server. This has to be changed on both the server and the clients. + +### Server side + +``` toml +[Peer] +AllowedIPs = 10.100.0.1/32 +``` + +Change this to + +``` toml +[Peer] +AllowedIPs = 10.100.0.1/32, 192.168.2.1/24 +``` + +if your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. + +### Client side + +Do the same in the `[Interface]` section. diff --git a/docs/guides/wireguard/overview.md b/docs/guides/wireguard/overview.md new file mode 100644 index 00000000..babbd8dd --- /dev/null +++ b/docs/guides/wireguard/overview.md @@ -0,0 +1,30 @@ +### Remote accessing Pi-hole using WireGuard + +WireGuard is an ***extremely simple yet fast and modern VPN*** that utilizes state-of-the-art cryptography. Comparing to other solutions, such as OpenVPN or IPsec, it aims to be **faster, simpler and leaner** while avoiding the massive overhead involved with other VPN solutions. +A combination of extremely high-speed cryptographic primitives and the fact that WireGuard lives +inside the Linux kernel means that secure networking can be very high-speed. +It intends to be considerably more performant than OpenVPN. + +WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many circumstances. + +There is no need to manage connections, be concerned about state, manage daemons, or worry about what's under the hood. WireGuard presents an extremely basic yet powerful interface. + +Using WireGuard is a modern and safe way to access your Pi-hole's capabilities remotely. Setting up a DNS server has become a simple task with Pi-hole's automated installer, which has resulted in many people knowingly--or unknowingly--creating an open resolver, which aids in DNS Amplification Attacks. + +WireGuard has been designed with ease-of-implementation and simplicity in mind. It is meant to be +easily implemented in very few lines of code, and easily auditable for security vulnerabilities. + +This article aims to provide a step-by-step walk-through on setting up a server running Pi-hole and WireGuard so you can securely connect to your Pi-hole's DNS (and *optionally* your entire internal network) from anywhere. + +**This tutorial walks you through the installation of a WireGuard server on your Pi-hole**. + +Via this VPN, you can: + +- use the full filtering capabilities of your Pi-hole +- access your Pi-hole dashboard remotely +- access all your internal devices (*optional*) +- reroute your entire Internet traffic through your Pi-hole (*optional*) + +from everywhere around the globe. + +{!abbreviations.md!} diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md new file mode 100644 index 00000000..13632222 --- /dev/null +++ b/docs/guides/wireguard/route-everything.md @@ -0,0 +1,13 @@ +Routing your entire Internet traffic is **optional**, however, it can be advantageous in cases where you are expecting eavesdropping on the network. This may not only happen in unsecure open Wi-Fi networks (airports, hotels, trains, etc.) but also in encrypted Wi-Fi networks where the creator of the network can monitor client activity. + +Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. + +To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your WireGuard config files: + +```toml +AllowedIPs = 0.0.0.0/0, ::/0 +``` + +Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. + +That's all you need to do. diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md new file mode 100644 index 00000000..da18b835 --- /dev/null +++ b/docs/guides/wireguard/server.md @@ -0,0 +1,110 @@ +# Installing the WireGuard server + + +!!! info "The terms "server" and "client"" + Usage of the terms `server` and `client` were purposefully chosen in this guide specifically to help both new users and existing OpenVPN users become familiar with the construction of WireGuard's configuration files. + + WireGuard documentation simply refers to both of these concepts as `peers`. + + +## Installing the server components + +Installing everything we will need for a `wireguard` connections is as simple as running: + +``` bash +sudo apt-get install wireguard wireguard-tools wireguard-dkms +``` + +For Ubuntu 18.04 and lower, you need to do some extra steps: + +``` bash +sudo add-apt-repository ppa:wireguard/wireguard +sudo apt update +sudo apt install wireguard wireguard-tools wireguard-dkms +``` + +## Initial configuration + +Each network interface has a private key and a list of peers. Each peer has a public key. Public keys are short and simple, and are used by peers to authenticate each other. They can be passed around for use in configuration files by any out-of-band method, similar to how one might send their SSH public key to a friend for access to a shell server. + +First, we create the folder containing our `wireguard` configuration: + +``` bash +sudo -i +cd /etc/wireguard +umask 077 +``` + +### Key generation + +Inhere, we generate a key-pair for the server: + +``` bash +wg genkey | tee server.key | wg pubkey > server.pub +``` + +### Creating the WireGuard configuration + +Create a config file + +``` bash +sudo nano /etc/wireguard/wg0.conf +``` + +and put the following into it: + +``` toml +[Interface] +Address = 10.100.0.1/24 +ListenPort = 44711 +SaveConfig = true +``` + +Then run + +``` bash +echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf +``` + +to copy the server's private key into your config file. + +## Forward port + +If the server is behind NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `44711/UDP`) from the router to the WireGuard server. + +## Start the server + +Register your server `wg0` as: + +``` bash +systemctl enable wg-quick@wg0.service +systemctl daemon-reload +systemctl start wg-quick@wg0 +``` + +If successful, you should not see any output. In case you get an error like + +``` plain +RTNETLINK answers: Operation not supported +Unable to access interface: Protocol not supported +``` + +you should check that the WireGuard kernel module is loaded with the command below: + +```bash +sudo modprobe wireguard +``` + +If you get an error saying the module is missing, try reinstalling WireGuard or restart your server and try again. This may happen when the WireGuard server is installed for a more recent kernel than you are currently running. This typically happens when you have neither updated nor restarted your system for a long time. + +## Check everything is running + +With the following command, you can check if your `wireguard` server is running: + +``` bash +wg +``` + +You can now continue to add clients. + +{!abbreviations.md!} diff --git a/mkdocs.yml b/mkdocs.yml index 5efd672f..505ae0ea 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -99,6 +99,15 @@ nav: - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md - 'Benchmarking': guides/benchmark.md + - 'Remote accessing Pi-hole using WireGuard': + - 'Overview': guides/wireguard/overview.md + - 'Concept': guides/wireguard/concept.md + - 'Install server': guides/wireguard/server.md + - 'Add client(s)': guides/wireguard/client.md + - 'Optional extra features': + - 'Make all local devices accessible': guides/wireguard/internal.md + - 'Reroute all Internet traffic': guides/wireguard/route-everything.md + - 'Troubleshooting': guides/wireguard/faq.md - 'Pi-hole and OpenVPN Server': - 'Overview': guides/vpn/overview.md - 'Installation': guides/vpn/installation.md From aa8268c1ff8e1d107b775d05d23be9947f6c21a4 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 14 Sep 2020 00:26:57 +0200 Subject: [PATCH 22/41] Further optimizations and corrections for the WireGuard guide Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 126 ++++++++++++++++------ docs/guides/wireguard/internal.md | 3 +- docs/guides/wireguard/route-everything.md | 6 +- docs/guides/wireguard/server.md | 42 ++++++-- mkdocs.yml | 16 +-- 5 files changed, 141 insertions(+), 52 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 359cb2fb..3ad79604 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -25,22 +25,64 @@ wg genpsk > NAME.psk ## Add client to server configuration -Add the following to your `/etc/wireguard/wg0.conf`: - -``` toml -[Peer] -Address = 10.100.0.2/24 # Replace this IP address for subsequent clients -AllowedIPs = 10.100.0.1/32 # This client is only allowed to talk to the server -``` - -Then run +Add the new client by running the command: ``` bash -echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf -echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf +wg set wg0 peer "$(cat NAME.pub)" preshared-key NAME.psk allowed-ips 10.100.0.2/32 ``` -to copy the clients's public and pre-shared keys into the server's config file. + +!!! info "Client IP address" + Make sure to increment the IP address for any further client! We add the first client with the IP address `10.100.0.2` in this example (`10.100.0.1` is the server) + + +Restart your server to have it save your client to its config file: + +``` bash +sudo service wg-quick@wg0 restart +``` + + +!!! info "Restarting is optional" + Note that restarting the WireGuard server is optional and can be skiped. The new client will be stored in the config file on the next restart of the system. However, in case of powerloss, you will loose your new client which is why we restarting the server here (if this can be afforded). + + +After a restart, the server file should look like: + +``` toml +[Interface] +Address = 10.100.0.1/24 +ListenPort = 44711 +SaveConfig = true +PrivateKey = XYZ123456ABC= # PrivateKey will be different + +[Peer] +Address = 10.100.0.2/24 +AllowedIPs = 10.100.0.1/32 +PublicKey = F+80gbmHVlOrU+es13S18oMEX2g= # PublicKey will be different +PresharedKey = 8cLaY8Bkd7PiUs0izYBQYVTEFlA= # PresharedKey will be different + +# Possibly further [Peer] lines +``` + +The command + +``` bash +wg +``` + +should tell you about your new client: + +``` plain +interface: wg0 + public key: XYZ123456ABC= ⬅ Your server's public key will be different + private key: (hidden) + listening port: 44711 + +peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different + preshared key: (hidden) + allowed ips: 10.100.0.2/32 +``` ## Create client configuration @@ -54,37 +96,25 @@ with the content ``` toml [Interface] -Address = 10.100.0.2/24 # Replace this IP address for subsequent clients -DNS = 10.100.0.1 # IP address of your Pi-hole -Domains = ~. # Enforce all DNS over the WireGuard connection +Address = 10.100.0.2/32 # Replace this IP address for subsequent clients +DNS = 10.100.0.1 # IP address of your server (Pi-hole) ``` +and add the private key of this client + ``` bash echo "PrivateKey = $(cat NAME.key)" >> NAME.conf ``` -Then add your server as the only peer for this client: +Next, add your server as peer for this client: ``` toml [Peer] -AllowedIPs = 10.0.0.1/24 +AllowedIPs = 10.100.0.0/24 Endpoint = [your public IP or domain]:44711 PersistentKeepalive = 25 ``` -Make sure that each IP is used only once. - - -??? info "About the `PersistentKeepalive` setting" - By default WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). - - When a peer is behind NAT or a firewall, it typically wants to be able to receive incoming packets even when it is not sending any packets itself. Because NAT and stateful firewalls keep track of "connections", if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called *persistent keepalives*. - - When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is `25` seconds. Setting it to 0 turns the feature off, which is the default. - - **TL;DR** If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the "connection" open in the eyes of NAT. - - Then add the public key of the server as well as the PSK for this connection: ``` bash @@ -94,6 +124,19 @@ echo "PresharedKey = $(cat NAME.psk)" >> NAME.conf That's it. + +??? info "About the `PersistentKeepalive` setting" + By default WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). + + When a peer is behind NAT or a firewall, it typically wants to be able to receive incoming packets even when it is not sending any packets itself. Because NAT and stateful firewalls keep track of "connections", if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called *persistent keepalives*. + + When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is `25` seconds. Setting it to 0 turns the feature off, which is the default. + + Handshakes are not the same as keep-alives. A handshake establishes a limited-time session of about 3 minutes. So, for about 3 minutes your client is able to send its keep-alive packets without requireing a new session. Then, when the session expires, sending a new keep-alive requires a new session for which you should see a new handshake. In practice, the client initiates a handshake earlier. + + **TL;DR** If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the "connection" open in the eyes of NAT. + + ## Copy config file to client You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: @@ -104,8 +147,31 @@ qrencode -t ansiutf8 -r NAME.conf (you may need to install `qrencode` using `sudo apt-get install qrencode`) +You can directly scan this QR code with the official WireGuard app after clicking on the blue plus symbol in the lower right corner. + ## Connect to your WireGuard VPN After creating/copying the connection information over to your client, you may use the client you prefer to connect to your system. Mind that setting up auto-start of the WireGuard connection may lead to issues if you are doing this too early (when the system cannot resolve DNS). See our [FAQ](faq.md) for further hints. +You can check if your client successfully connected by, once again, running + +``` plain +wg +``` + +on the server. It should show some traffic for your client if everything works: + +``` plain +interface: wg0 + public key: XYZ123456ABC= ⬅ Your server's public key will be different + private key: (hidden) + listening port: 44711 + +peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different + preshared key: (hidden) + allowed ips: 10.100.0.2/32 + latest handshake: 32 seconds ago + transfer: 3.43 KiB received, 188 B sent +``` + {!abbreviations.md!} diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 2405b655..436c42e0 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -21,6 +21,7 @@ If you see the options repeated like ``` plain net.ipv4.ip_forward=1 +net.ipv6.conf.all.forwarding = 1 ``` they were enabled successfully. @@ -68,4 +69,4 @@ if your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. ### Client side -Do the same in the `[Interface]` section. +Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature. It is possible to add this only for a few clients, leaving the others isolated to only the Pi-hole server itself. diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index 13632222..0aeebaa8 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -2,7 +2,7 @@ Routing your entire Internet traffic is **optional**, however, it can be advanta Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. -To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your WireGuard config files: +To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your clients's WireGuard config files: ```toml AllowedIPs = 0.0.0.0/0, ::/0 @@ -10,4 +10,6 @@ AllowedIPs = 0.0.0.0/0, ::/0 Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. -That's all you need to do. +That's all you need to do. You should use an online check (e.g. www.wieistmeineip.de) to check if your IP changed to the public IP address of your WireGuard server after this change up. It is possible to add this change only for a few clients, leaving the others without a full tunnel for all traffic (e.g., where this is not necessary or not desired). + +{!abbreviations.md!} diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index da18b835..7c2ff56b 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -4,7 +4,7 @@ !!! info "The terms "server" and "client"" Usage of the terms `server` and `client` were purposefully chosen in this guide specifically to help both new users and existing OpenVPN users become familiar with the construction of WireGuard's configuration files. - WireGuard documentation simply refers to both of these concepts as `peers`. + WireGuard itself simply refers to all connected devices as `peers`. It consitutes a connection between computers. ## Installing the server components @@ -82,20 +82,25 @@ systemctl daemon-reload systemctl start wg-quick@wg0 ``` -If successful, you should not see any output. In case you get an error like +If successful, you should not see any output. -``` plain -RTNETLINK answers: Operation not supported -Unable to access interface: Protocol not supported -``` + +??? warning "Error: RTNETLINK answers: Operation not supported" + In case you get an error like -you should check that the WireGuard kernel module is loaded with the command below: + ``` plain + RTNETLINK answers: Operation not supported + Unable to access interface: Protocol not supported + ``` -```bash -sudo modprobe wireguard -``` + you should check that the WireGuard kernel module is loaded with the command below: -If you get an error saying the module is missing, try reinstalling WireGuard or restart your server and try again. This may happen when the WireGuard server is installed for a more recent kernel than you are currently running. This typically happens when you have neither updated nor restarted your system for a long time. + ```bash + sudo modprobe wireguard + ``` + + If you get an error saying the module is missing, try reinstalling WireGuard or restart your server and try again. This may happen when the WireGuard server is installed for a more recent kernel than you are currently running. This typically happens when you have neither updated nor restarted your system for a long time. + ## Check everything is running @@ -105,6 +110,21 @@ With the following command, you can check if your `wireguard` server is running: wg ``` +The output should look like the following: + +``` plain +interface: wg0 + public key: XYZ123456ABC= ⬅ Your public key will be different + private key: (hidden) + listening port: 44711 +``` + +Your public key will be different to ours. This is expected (you just created your own key above). + +## Set your Pi-hole to listen on all interfaces + +On your [Settings page (tab DNS)](http://pi.hole/admin/settings.php?tab=dns), ensure you set the listing mode of your Pi-hole to one of the `Listen of all interfaces` settings. The top one is perferred as it adds a bit of additional safety. Your WireGuard peers/clients will be correctly recognized as being only one hop away. + You can now continue to add clients. {!abbreviations.md!} diff --git a/mkdocs.yml b/mkdocs.yml index 505ae0ea..b4178ef8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -92,14 +92,7 @@ nav: - 'How to sign-off commits': guides/github/how-to-signoff.md - 'Guides': - 'Pi-hole as All-Around DNS Solution': guides/unbound.md - - 'Configuring DNS-Over-HTTPS on Pi-hole': guides/dns-over-https.md - - 'Upstream DNS Providers': guides/upstream-dns-providers.md - - 'Editing Whitelist and Blacklist': guides/whitelist-blacklist.md - - 'Configuring NGINX for Pi-hole': guides/nginx-configuration.md - - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md - - 'Benchmarking': guides/benchmark.md - - 'Remote accessing Pi-hole using WireGuard': + - 'Remote access using WireGuard': - 'Overview': guides/wireguard/overview.md - 'Concept': guides/wireguard/concept.md - 'Install server': guides/wireguard/server.md @@ -108,6 +101,13 @@ nav: - 'Make all local devices accessible': guides/wireguard/internal.md - 'Reroute all Internet traffic': guides/wireguard/route-everything.md - 'Troubleshooting': guides/wireguard/faq.md + - 'Configuring DNS-Over-HTTPS on Pi-hole': guides/dns-over-https.md + - 'Upstream DNS Providers': guides/upstream-dns-providers.md + - 'Editing Whitelist and Blacklist': guides/whitelist-blacklist.md + - 'Configuring NGINX for Pi-hole': guides/nginx-configuration.md + - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md + - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md + - 'Benchmarking': guides/benchmark.md - 'Pi-hole and OpenVPN Server': - 'Overview': guides/vpn/overview.md - 'Installation': guides/vpn/installation.md From e63dbb4c55a05ce7eb8233f34f516bb8e7cda46f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 14 Sep 2020 00:42:32 +0200 Subject: [PATCH 23/41] Encourage users to test for DNS leaks after setting up their clients Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 14 ++++++++++---- docs/guides/wireguard/server.md | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 3ad79604..d8938195 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -52,7 +52,7 @@ After a restart, the server file should look like: ``` toml [Interface] Address = 10.100.0.1/24 -ListenPort = 44711 +ListenPort = 47111 SaveConfig = true PrivateKey = XYZ123456ABC= # PrivateKey will be different @@ -77,7 +77,7 @@ should tell you about your new client: interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) - listening port: 44711 + listening port: 47111 peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different preshared key: (hidden) @@ -111,7 +111,7 @@ Next, add your server as peer for this client: ``` toml [Peer] AllowedIPs = 10.100.0.0/24 -Endpoint = [your public IP or domain]:44711 +Endpoint = [your public IP or domain]:47111 PersistentKeepalive = 25 ``` @@ -165,7 +165,7 @@ on the server. It should show some traffic for your client if everything works: interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) - listening port: 44711 + listening port: 47111 peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different preshared key: (hidden) @@ -174,4 +174,10 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen transfer: 3.43 KiB received, 188 B sent ``` +## Test for DNS leaks + +You should run a DNS leak test on [www.dnsleaktest.com](https://www.dnsleaktest.com) to ensure your WireGuard tunnel does not leak DNS requests (so all are processed by your Pi-hole). The expected outcome is that you should only see DNS servers belonging to the upstream DNS destination you selected in Pi-hole. If you configured [Pi-hole as All-Around DNS Solution](../unbound.md), you should only see the public IP address of your WireGuard server and no other DNS server. + +See also [What is a DNS leak and why should I care?](https://www.dnsleaktest.com/what-is-a-dns-leak.html) (external link). + {!abbreviations.md!} diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 7c2ff56b..0955493a 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -56,7 +56,7 @@ and put the following into it: ``` toml [Interface] Address = 10.100.0.1/24 -ListenPort = 44711 +ListenPort = 47111 SaveConfig = true ``` @@ -70,7 +70,7 @@ to copy the server's private key into your config file. ## Forward port -If the server is behind NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `44711/UDP`) from the router to the WireGuard server. +If the server is behind NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `47111/UDP`) from the router to the WireGuard server. ## Start the server @@ -116,7 +116,7 @@ The output should look like the following: interface: wg0 public key: XYZ123456ABC= ⬅ Your public key will be different private key: (hidden) - listening port: 44711 + listening port: 47111 ``` Your public key will be different to ours. This is expected (you just created your own key above). From b16365d95617250659e1bfcc682c1eafaf9ba7d1 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 14 Sep 2020 22:02:20 +0200 Subject: [PATCH 24/41] Add instructions how to compile WireGuard from source Signed-off-by: DL6ER --- docs/guides/wireguard/server.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 0955493a..c9739fc2 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -23,6 +23,35 @@ sudo apt update sudo apt install wireguard wireguard-tools wireguard-dkms ``` +If there is no `wireguard` package available for your system, you can follow the instructions below to compile WireGuard from source. + + +???+ info "Compile WireGuard from source" + + With the following commands, you can install WireGuard from source + + ``` bash + sudo apt update && sudo apt upgrade -y + sudo apt install raspberrypi-kernel-headers libmnl-dev libelf-dev build-essential git -y + git clone https://git.zx2c4.com/WireGuard + cd WireGuard/src + sudo make + sudo make install + ``` + + With these commands, you can update your locally compiled WireGuard at any time: + + ``` bash + cd WireGuard/ + git pull + cd src + sudo make + sudo make install + ``` + + The ZX2C4 git repository is the official source for `wireguard-linux`, see [WireGuard#Repositories](https://www.wireguard.com/repositories/) (external link) + + ## Initial configuration Each network interface has a private key and a list of peers. Each peer has a public key. Public keys are short and simple, and are used by peers to authenticate each other. They can be passed around for use in configuration files by any out-of-band method, similar to how one might send their SSH public key to a friend for access to a shell server. From 126cc21092382e17a7eb738d56d46559ee3257a9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 23 Sep 2020 17:38:27 +0200 Subject: [PATCH 25/41] Use backports for compiling WireGuard from source. This makes it compatible also with older kernels. Signed-off-by: DL6ER --- docs/guides/wireguard/server.md | 59 +++++++++++++++++++++++++-------- mkdocs.yml | 3 ++ 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index c9739fc2..fd9dc5f9 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -26,27 +26,60 @@ sudo apt install wireguard wireguard-tools wireguard-dkms If there is no `wireguard` package available for your system, you can follow the instructions below to compile WireGuard from source. -???+ info "Compile WireGuard from source" +??? info "Compile WireGuard from source" - With the following commands, you can install WireGuard from source + With the following commands, you can install WireGuard from source as a backport of the WireGuard kernel module for Linux to 3.10 ≤ kernel ≤ 5.5 as an out-of-tree module. More recent kernels already include WireGuard themselves and you only need to install the `wireguard` tools. + + ### Update your local system ``` bash sudo apt update && sudo apt upgrade -y - sudo apt install raspberrypi-kernel-headers libmnl-dev libelf-dev build-essential git -y - git clone https://git.zx2c4.com/WireGuard - cd WireGuard/src - sudo make - sudo make install ``` - With these commands, you can update your locally compiled WireGuard at any time: + ### Install the toolchain + + === "Raspberry Pi" + + ``` bash + sudo apt install -y raspberrypi-kernel-headers libelf-dev build-essential pkg-config git + ``` + + === "Linux" + + ``` bash + sudo apt install -y linux-headers-$(uname -r) libelf-dev build-essential libmnl-dev git + ``` + + ## Download and compile the `wireguard` module ``` bash - cd WireGuard/ - git pull - cd src - sudo make - sudo make install + git clone https://git.zx2c4.com/wireguard-linux-compat + make -C wireguard-linux-compat/src -j$(nproc) + sudo make -C wireguard-linux-compat/src install + ``` + + You can ignore messages like + + ``` plain + Warning: modules_install: missing 'System.map' file. Skipping depmod. + ``` + + !!! info "Check the module installation was successful" + + Run + + ``` bash + sudo modprobe wireguard + ``` + + If there is no output, `wireguard` was loaded correctly. Note that it may be necessary to re-install the `wireguard` module when you update your system's kernel. + + ## Download and compile the `wireguard` tools (`wg`, etc.) + + ``` bash + git clone https://git.zx2c4.com/wireguard-tools + make -C wireguard-tools/src -j$(nproc) + sudo make -C wireguard-tools/src install ``` The ZX2C4 git repository is the official source for `wireguard-linux`, see [WireGuard#Repositories](https://www.wireguard.com/repositories/) (external link) diff --git a/mkdocs.yml b/mkdocs.yml index b4178ef8..cdc85081 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -39,6 +39,9 @@ markdown_extensions: - pymdownx.extra # (https://facelessuser.github.io/pymdown-extensions/extensions/details/) - pymdownx.details + # Tabbed provides a syntax to easily add tabbed Markdown content. + # https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/ + - pymdownx.tabbed # Adds syntax for defining footnotes in Markdown documents (https://python-markdown.github.io/extensions/footnotes/) - footnotes # Adds the ability to define abbreviations From 50913fd06c8347cd7d03c7700919385e39bcbf48 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 23 Sep 2020 22:17:17 +0200 Subject: [PATCH 26/41] Do not use auto-save so the server's config file may be edited at any time Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 15 ++++++--------- docs/guides/wireguard/server.md | 10 +++++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index d8938195..6fc18450 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -28,7 +28,10 @@ wg genpsk > NAME.psk Add the new client by running the command: ``` bash -wg set wg0 peer "$(cat NAME.pub)" preshared-key NAME.psk allowed-ips 10.100.0.2/32 +echo "[Peer]" >> /etc/wireguard/wg0.conf +echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf +echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf +echo "AllowedIPs = 10.100.0.2/32" >> /etc/wireguard/wg0.conf ``` @@ -36,17 +39,12 @@ wg set wg0 peer "$(cat NAME.pub)" preshared-key NAME.psk allowed-ips 10.100.0.2/ Make sure to increment the IP address for any further client! We add the first client with the IP address `10.100.0.2` in this example (`10.100.0.1` is the server) -Restart your server to have it save your client to its config file: +Restart your server to load the new client config: ``` bash sudo service wg-quick@wg0 restart ``` - -!!! info "Restarting is optional" - Note that restarting the WireGuard server is optional and can be skiped. The new client will be stored in the config file on the next restart of the system. However, in case of powerloss, you will loose your new client which is why we restarting the server here (if this can be afforded). - - After a restart, the server file should look like: ``` toml @@ -57,10 +55,9 @@ SaveConfig = true PrivateKey = XYZ123456ABC= # PrivateKey will be different [Peer] -Address = 10.100.0.2/24 -AllowedIPs = 10.100.0.1/32 PublicKey = F+80gbmHVlOrU+es13S18oMEX2g= # PublicKey will be different PresharedKey = 8cLaY8Bkd7PiUs0izYBQYVTEFlA= # PresharedKey will be different +AllowedIPs = 10.100.0.2/32 # Possibly further [Peer] lines ``` diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index fd9dc5f9..8ff38d95 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -119,13 +119,13 @@ and put the following into it: [Interface] Address = 10.100.0.1/24 ListenPort = 47111 -SaveConfig = true ``` Then run ``` bash echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf +exit # Exit the sudo session ``` to copy the server's private key into your config file. @@ -139,9 +139,9 @@ If the server is behind NAT, be sure to forward the specified port on which Wire Register your server `wg0` as: ``` bash -systemctl enable wg-quick@wg0.service -systemctl daemon-reload -systemctl start wg-quick@wg0 +sudo systemctl enable wg-quick@wg0.service +sudo systemctl daemon-reload +sudo systemctl start wg-quick@wg0 ``` If successful, you should not see any output. @@ -169,7 +169,7 @@ If successful, you should not see any output. With the following command, you can check if your `wireguard` server is running: ``` bash -wg +sudo wg ``` The output should look like the following: From 8e08b657b7f0e78736b0a3d6b84981d4f74e07bf Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 23 Sep 2020 23:09:37 +0200 Subject: [PATCH 27/41] Ensure we configure also an internal IPv6 tunnel (will be transported transparently over IPv4 on the outside) Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 23 ++++++++++++----------- docs/guides/wireguard/server.md | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 6fc18450..03550e68 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -31,25 +31,25 @@ Add the new client by running the command: echo "[Peer]" >> /etc/wireguard/wg0.conf echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf -echo "AllowedIPs = 10.100.0.2/32" >> /etc/wireguard/wg0.conf +echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf ``` !!! info "Client IP address" - Make sure to increment the IP address for any further client! We add the first client with the IP address `10.100.0.2` in this example (`10.100.0.1` is the server) + Make sure to increment the IP address for any further client! We add the first client with the IP addresses `10.100.0.2` and `fd08:4711::2/128` in this example (`10.100.0.1` and `fd08:4711::1/128` are the server) Restart your server to load the new client config: ``` bash -sudo service wg-quick@wg0 restart +systemctl restart wg-quick@wg0 ``` After a restart, the server file should look like: ``` toml [Interface] -Address = 10.100.0.1/24 +Address = 10.100.0.1/24, fd08::1/128 ListenPort = 47111 SaveConfig = true PrivateKey = XYZ123456ABC= # PrivateKey will be different @@ -57,7 +57,7 @@ PrivateKey = XYZ123456ABC= # PrivateKey will be different [Peer] PublicKey = F+80gbmHVlOrU+es13S18oMEX2g= # PublicKey will be different PresharedKey = 8cLaY8Bkd7PiUs0izYBQYVTEFlA= # PresharedKey will be different -AllowedIPs = 10.100.0.2/32 +AllowedIPs = 10.100.0.2/32, fd08:4711::2/128 # Possibly further [Peer] lines ``` @@ -78,7 +78,7 @@ interface: wg0 peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different preshared key: (hidden) - allowed ips: 10.100.0.2/32 + allowed ips: 10.100.0.2/32, fd08::2/128 ``` ## Create client configuration @@ -93,8 +93,8 @@ with the content ``` toml [Interface] -Address = 10.100.0.2/32 # Replace this IP address for subsequent clients -DNS = 10.100.0.1 # IP address of your server (Pi-hole) +Address = 10.100.0.2/32, fd08:4711::2/128 # Replace this IP address for subsequent clients +DNS = 10.100.0.1 # IP address of your server (Pi-hole) ``` and add the private key of this client @@ -107,7 +107,7 @@ Next, add your server as peer for this client: ``` toml [Peer] -AllowedIPs = 10.100.0.0/24 +AllowedIPs = 10.100.0.0/24, fd08::/64 Endpoint = [your public IP or domain]:47111 PersistentKeepalive = 25 ``` @@ -117,6 +117,7 @@ Then add the public key of the server as well as the PSK for this connection: ``` bash echo "PublicKey = $(cat server.pub)" >> NAME.conf echo "PresharedKey = $(cat NAME.psk)" >> NAME.conf +exit ``` That's it. @@ -139,7 +140,7 @@ That's it. You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: ``` bash -qrencode -t ansiutf8 -r NAME.conf +sudo qrencode -t ansiutf8 -r /etc/wireguard/NAME.conf ``` (you may need to install `qrencode` using `sudo apt-get install qrencode`) @@ -153,7 +154,7 @@ After creating/copying the connection information over to your client, you may u You can check if your client successfully connected by, once again, running ``` plain -wg +sudo wg ``` on the server. It should show some traffic for your client if everything works: diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 8ff38d95..6e74b529 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -117,7 +117,7 @@ and put the following into it: ``` toml [Interface] -Address = 10.100.0.1/24 +Address = 10.100.0.1/24, fd08:4711::1/64 ListenPort = 47111 ``` From 2c5b7b2d5c725f53acbd3ef75197f2e065ab0393 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 23 Sep 2020 23:42:01 +0200 Subject: [PATCH 28/41] Add hint that IP forwarding already needs to be enabled for routing the entire Internet traffic Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 2 +- docs/guides/wireguard/internal.md | 22 ++++++++++++---------- docs/guides/wireguard/route-everything.md | 10 +++++++++- mkdocs.yml | 6 +++--- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 03550e68..c326ea27 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -94,7 +94,7 @@ with the content ``` toml [Interface] Address = 10.100.0.2/32, fd08:4711::2/128 # Replace this IP address for subsequent clients -DNS = 10.100.0.1 # IP address of your server (Pi-hole) +DNS = 10.100.0.1 # IP address of your server (Pi-hole) ``` and add the private key of this client diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 436c42e0..399a87b2 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -1,4 +1,4 @@ -# Access devices in the internal network through the WireGuard tunnel +# Access internal devices through the WireGuard tunnel ## Enable IP forwarding on the server @@ -33,7 +33,7 @@ A properly configured firewall is ***highly*** recommended for any Internet-faci !!! info "Optional for NAT" If the server is behind a router and receives traffic via NAT, these iptables rules are not needed. -On your server, add the following to the `[INTERFACE]` section: +On your server, add the following to the `[INTERFACE]` section of your `/etc/wireguard/wg0.conf`: ``` toml PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE @@ -53,19 +53,21 @@ In our standard configuration, we have configured the clients in such a way that ### Server side -``` toml -[Peer] -AllowedIPs = 10.100.0.1/32 -``` - -Change this to +Change the allowed addresses in your `/etc/wireguard/wg0.conf` from ``` toml [Peer] -AllowedIPs = 10.100.0.1/32, 192.168.2.1/24 +AllowedIPs = 10.100.0.1/32, fd08:4711::1/64 ``` -if your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. +to + +``` toml +[Peer] +AllowedIPs = 10.100.0.1/32, fd08:4711::1/64, 192.168.2.1/24 +``` + +assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. ### Client side diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index 0aeebaa8..d3699b08 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -1,14 +1,22 @@ +# Route the entire Internet traffic through the WireGuard tunnel + Routing your entire Internet traffic is **optional**, however, it can be advantageous in cases where you are expecting eavesdropping on the network. This may not only happen in unsecure open Wi-Fi networks (airports, hotels, trains, etc.) but also in encrypted Wi-Fi networks where the creator of the network can monitor client activity. Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. +!!! info "Ensure you're already forwarding traffic" + The following assumes you have already prepared your Pi-hole for [IP forwarding](internal.md). If this is not the case, follow the steps over there before continuing here. + To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your clients's WireGuard config files: ```toml AllowedIPs = 0.0.0.0/0, ::/0 ``` -Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. + +!!! warning "Change this setting only on your clients" + Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. + That's all you need to do. You should use an online check (e.g. www.wieistmeineip.de) to check if your IP changed to the public IP address of your WireGuard server after this change up. It is possible to add this change only for a few clients, leaving the others without a full tunnel for all traffic (e.g., where this is not necessary or not desired). diff --git a/mkdocs.yml b/mkdocs.yml index cdc85081..e3664b1a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -95,14 +95,14 @@ nav: - 'How to sign-off commits': guides/github/how-to-signoff.md - 'Guides': - 'Pi-hole as All-Around DNS Solution': guides/unbound.md - - 'Remote access using WireGuard': + - 'WireGuard VPN': - 'Overview': guides/wireguard/overview.md - 'Concept': guides/wireguard/concept.md - 'Install server': guides/wireguard/server.md - 'Add client(s)': guides/wireguard/client.md - 'Optional extra features': - - 'Make all local devices accessible': guides/wireguard/internal.md - - 'Reroute all Internet traffic': guides/wireguard/route-everything.md + - 'Make local devices accessible': guides/wireguard/internal.md + - 'Tunnel all Internet traffic': guides/wireguard/route-everything.md - 'Troubleshooting': guides/wireguard/faq.md - 'Configuring DNS-Over-HTTPS on Pi-hole': guides/dns-over-https.md - 'Upstream DNS Providers': guides/upstream-dns-providers.md From 63b4bd658717f84b547f396894b7e302ee5a683b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 24 Sep 2020 23:53:25 +0200 Subject: [PATCH 29/41] Add hint to add full-tunnel as second profile Signed-off-by: DL6ER --- docs/guides/wireguard/internal.md | 14 +++++++++++--- docs/guides/wireguard/route-everything.md | 11 +++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 399a87b2..cbecca05 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -64,11 +64,19 @@ to ``` toml [Peer] -AllowedIPs = 10.100.0.1/32, fd08:4711::1/64, 192.168.2.1/24 +AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` -assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. +assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. The change `10.100.0.1/32` to `10.100.0.0/24` also allows your WireGuard peers to see each other. ### Client side -Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature. It is possible to add this only for a few clients, leaving the others isolated to only the Pi-hole server itself. +Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature: + +``` toml +[Peer] +AllowedIPs = 10.0.0.0/24, fd08:4711::/64, 192.168.2.0/24 +``` + + +It is possible to add this only for a few clients, leaving the others isolated to only the Pi-hole server itself. diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index d3699b08..cd578a5a 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -4,8 +4,15 @@ Routing your entire Internet traffic is **optional**, however, it can be advanta Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. -!!! info "Ensure you're already forwarding traffic" - The following assumes you have already prepared your Pi-hole for [IP forwarding](internal.md). If this is not the case, follow the steps over there before continuing here. + +!!! info "Create a second profile" + Instead of editing your existing configuration, you can easily add a new one with the modified `AllowedIPs` line as above. This will give you two tunnel variants and you decide - at any time from mobile - which variant you want. The one with only the DNS traffic being safely forwarded to your Pi-hole or the variant where your entire Internet traffic is encrypted and sent through your Pi-hole. You can choose at any time which is the best solution in your current situation (e.g., trusted network, unencrypted airport Wi-Fi, etc.). + + + +!!! warning "Ensure you're already forwarding traffic" + The following assumes you have already prepared your Pi-hole for [IP forwarding](internal.md#enable-ip-forwarding-on-the-server) and [enabled NAT](internal.md#enable-nat-on-the-server). If this is not the case, follow the steps over there before continuing here. + To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your clients's WireGuard config files: From 2eb51183654b96b1b493d73227e4bbf1e3b4133d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 24 Sep 2020 23:59:25 +0200 Subject: [PATCH 30/41] Use BASH variable for client name so the client generation can be scripted more easily Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index c326ea27..d1ed1db4 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -12,7 +12,8 @@ We generate a key-pair for the client `NAME` (replace accordingly everywhere bel sudo -i cd /etc/wireguard umask 077 -wg genkey | tee NAME.key | wg pubkey > NAME.pub +name="client_name" +wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub" ``` ## PSK Key generation @@ -20,7 +21,7 @@ wg genkey | tee NAME.key | wg pubkey > NAME.pub We furthermore recommend generating a pre-shared key (PSK) in addition to the keys above. This adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography and is mainly for post-quantum resistance. A pre-shared key should be generated for each peer pair and *should not be reused*. ``` bash -wg genpsk > NAME.psk +wg genpsk > "${name}.psk" ``` ## Add client to server configuration @@ -29,8 +30,8 @@ Add the new client by running the command: ``` bash echo "[Peer]" >> /etc/wireguard/wg0.conf -echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf -echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf +echo "PublicKey = $(cat "${name}.pub")" >> /etc/wireguard/wg0.conf +echo "PresharedKey = $(cat "${name}.psk")" >> /etc/wireguard/wg0.conf echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf ``` @@ -86,7 +87,7 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen Create a dedicated config file for your new client: ``` bash -nano NAME.conf +nano "${name}.conf" ``` with the content @@ -100,7 +101,7 @@ DNS = 10.100.0.1 # IP address of your server (Pi-hole) and add the private key of this client ``` bash -echo "PrivateKey = $(cat NAME.key)" >> NAME.conf +echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf" ``` Next, add your server as peer for this client: @@ -115,8 +116,8 @@ PersistentKeepalive = 25 Then add the public key of the server as well as the PSK for this connection: ``` bash -echo "PublicKey = $(cat server.pub)" >> NAME.conf -echo "PresharedKey = $(cat NAME.psk)" >> NAME.conf +echo "PublicKey = $(cat server.pub)" >> "${name}.conf" +echo "PresharedKey = $(cat "${name}.psk")" >> "${name}.conf" exit ``` @@ -140,7 +141,7 @@ That's it. You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: ``` bash -sudo qrencode -t ansiutf8 -r /etc/wireguard/NAME.conf +sudo qrencode -t ansiutf8 -r "/etc/wireguard/${name}.conf" ``` (you may need to install `qrencode` using `sudo apt-get install qrencode`) From df949dc2058aace873c15246aeeed19545e3f215 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 25 Sep 2020 00:06:07 +0200 Subject: [PATCH 31/41] Add a copy-and-paste friendly box with *all* commands needed to add a new client in one shot. Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 44 ++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index d1ed1db4..49bdddc9 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -4,6 +4,38 @@ Adding clients is really simple and easy. The process for setting up a client is For each new client, the following steps must be taken. For the sake of simplicity, we will create the config file on the server itself. This, however, means that you need to transfer the config file *securely* to your server as it contains the private key of your client. An alternative way of doing this is to generate the configuration locally on your client and add the necessary lines to your server's configuration. + +??? info "All commands described below at once" + ``` bash + sudo -i + cd /etc/wireguard + umask 077 + + name="client_name" + + wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub" + wg genpsk > "${name}.psk" + + echo "[Peer]" >> /etc/wireguard/wg0.conf + echo "PublicKey = $(cat "${name}.pub")" >> /etc/wireguard/wg0.conf + echo "PresharedKey = $(cat "${name}.psk")" >> /etc/wireguard/wg0.conf + echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf + + systemctl restart wg-quick@wg0 + + echo "[Interface]" > "${name}.conf" + echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> "${name}.conf" # May need editing + echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hole's IP + echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf" + echo "PublicKey = $(cat server.pub)" >> "${name}.conf" + echo "PresharedKey = $(cat "${name}.psk")" >> "${name}.conf" + + qrencode -t ansiutf8 -r "${name}.conf" + + exit + ``` + + ## Key generation We generate a key-pair for the client `NAME` (replace accordingly everywhere below): @@ -87,15 +119,9 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen Create a dedicated config file for your new client: ``` bash -nano "${name}.conf" -``` - -with the content - -``` toml -[Interface] -Address = 10.100.0.2/32, fd08:4711::2/128 # Replace this IP address for subsequent clients -DNS = 10.100.0.1 # IP address of your server (Pi-hole) +echo "[Interface]" > "${name}.conf" +echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> "${name}.conf" # May need editing +echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hole's IP ``` and add the private key of this client From cd606b24e27988a61b8b0df2409dca53b6cbd411 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Mon, 19 Oct 2020 08:19:29 +0300 Subject: [PATCH 32/41] Remove redundant spaces after fenced codeblocks --- docs/guides/wireguard/client.md | 32 +++++++++++++-------------- docs/guides/wireguard/faq.md | 12 +++++------ docs/guides/wireguard/internal.md | 14 ++++++------ docs/guides/wireguard/server.md | 36 +++++++++++++++---------------- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 49bdddc9..cc476e3a 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -6,7 +6,7 @@ For each new client, the following steps must be taken. For the sake of simplici ??? info "All commands described below at once" - ``` bash + ```bash sudo -i cd /etc/wireguard umask 077 @@ -40,7 +40,7 @@ For each new client, the following steps must be taken. For the sake of simplici We generate a key-pair for the client `NAME` (replace accordingly everywhere below): -``` bash +```bash sudo -i cd /etc/wireguard umask 077 @@ -52,7 +52,7 @@ wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub" We furthermore recommend generating a pre-shared key (PSK) in addition to the keys above. This adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography and is mainly for post-quantum resistance. A pre-shared key should be generated for each peer pair and *should not be reused*. -``` bash +```bash wg genpsk > "${name}.psk" ``` @@ -60,7 +60,7 @@ wg genpsk > "${name}.psk" Add the new client by running the command: -``` bash +```bash echo "[Peer]" >> /etc/wireguard/wg0.conf echo "PublicKey = $(cat "${name}.pub")" >> /etc/wireguard/wg0.conf echo "PresharedKey = $(cat "${name}.psk")" >> /etc/wireguard/wg0.conf @@ -74,13 +74,13 @@ echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf Restart your server to load the new client config: -``` bash +```bash systemctl restart wg-quick@wg0 ``` After a restart, the server file should look like: -``` toml +```toml [Interface] Address = 10.100.0.1/24, fd08::1/128 ListenPort = 47111 @@ -97,13 +97,13 @@ AllowedIPs = 10.100.0.2/32, fd08:4711::2/128 The command -``` bash +```bash wg ``` should tell you about your new client: -``` plain +```plain interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) @@ -118,7 +118,7 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen Create a dedicated config file for your new client: -``` bash +```bash echo "[Interface]" > "${name}.conf" echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> "${name}.conf" # May need editing echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hole's IP @@ -126,13 +126,13 @@ echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hol and add the private key of this client -``` bash +```bash echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf" ``` Next, add your server as peer for this client: -``` toml +```toml [Peer] AllowedIPs = 10.100.0.0/24, fd08::/64 Endpoint = [your public IP or domain]:47111 @@ -141,7 +141,7 @@ PersistentKeepalive = 25 Then add the public key of the server as well as the PSK for this connection: -``` bash +```bash echo "PublicKey = $(cat server.pub)" >> "${name}.conf" echo "PresharedKey = $(cat "${name}.psk")" >> "${name}.conf" exit @@ -158,7 +158,7 @@ That's it. When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is `25` seconds. Setting it to 0 turns the feature off, which is the default. Handshakes are not the same as keep-alives. A handshake establishes a limited-time session of about 3 minutes. So, for about 3 minutes your client is able to send its keep-alive packets without requireing a new session. Then, when the session expires, sending a new keep-alive requires a new session for which you should see a new handshake. In practice, the client initiates a handshake earlier. - + **TL;DR** If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the "connection" open in the eyes of NAT. @@ -166,7 +166,7 @@ That's it. You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: -``` bash +```bash sudo qrencode -t ansiutf8 -r "/etc/wireguard/${name}.conf" ``` @@ -180,13 +180,13 @@ After creating/copying the connection information over to your client, you may u You can check if your client successfully connected by, once again, running -``` plain +```plain sudo wg ``` on the server. It should show some traffic for your client if everything works: -``` plain +```plain interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md index e92e3ecd..0ec039b6 100644 --- a/docs/guides/wireguard/faq.md +++ b/docs/guides/wireguard/faq.md @@ -9,13 +9,13 @@ Host names cannot be resolved during startup. This may lead to a five minutes de If the IP changes while the connection is running, resolving the new IP address fails otten. Reconnect using -``` bash +```bash sudo ifdown wg0 && sudo ifup wg0 ``` To achieve a permanent solution, one can install a `cron` job which restarts the connection automatically whenever a change is detected. This avoids excessive restarts of the interface. Example script (taken from [Ubuntuusers Wiki](https://wiki.ubuntuusers.de/WireGuard)): -``` bash +```bash #!/bin/bash # Check state of wg0 interface wgstatus=$(wg) @@ -42,11 +42,11 @@ fi Store this file as `/home/[user name]/wg-restart.sh` and add it to your `crontab`: -``` bash +```bash sudo crontab -e ``` -``` plain +```plain */10 * * * * bash /home/[user name]/wg-restart.sh # Runs the script every 10 minutes ``` @@ -54,7 +54,7 @@ sudo crontab -e Users of NetworkManager should make sure that it is not managing the WireGuard interface(s). For example, create the configuration file `/etc/NetworkManager/conf.d/unmanaged.conf` with content -``` toml +```toml [keyfile] unmanaged-devices=interface-name:wg* ``` @@ -77,7 +77,7 @@ The solution is to use networking software that supports `resolvconf`. Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client: -``` toml +```toml [Interface] MTU = 1500 ``` diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index cbecca05..8884cf6e 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -4,7 +4,7 @@ Enable IP forwarding on your server by removing the comments in front of -``` toml +```toml net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 ``` @@ -13,13 +13,13 @@ in the file `/etc/sysctl.d/99-sysctl.conf` Then apply the new option with the command below. -``` bash +```bash sudo sysctl -p ``` If you see the options repeated like -``` plain +```plain net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding = 1 ``` @@ -35,7 +35,7 @@ A properly configured firewall is ***highly*** recommended for any Internet-faci On your server, add the following to the `[INTERFACE]` section of your `/etc/wireguard/wg0.conf`: -``` toml +```toml PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` @@ -55,14 +55,14 @@ In our standard configuration, we have configured the clients in such a way that Change the allowed addresses in your `/etc/wireguard/wg0.conf` from -``` toml +```toml [Peer] AllowedIPs = 10.100.0.1/32, fd08:4711::1/64 ``` to -``` toml +```toml [Peer] AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` @@ -73,7 +73,7 @@ assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254 Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature: -``` toml +```toml [Peer] AllowedIPs = 10.0.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 6e74b529..af539bc2 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -11,13 +11,13 @@ Installing everything we will need for a `wireguard` connections is as simple as running: -``` bash +```bash sudo apt-get install wireguard wireguard-tools wireguard-dkms ``` For Ubuntu 18.04 and lower, you need to do some extra steps: -``` bash +```bash sudo add-apt-repository ppa:wireguard/wireguard sudo apt update sudo apt install wireguard wireguard-tools wireguard-dkms @@ -32,7 +32,7 @@ If there is no `wireguard` package available for your system, you can follow the ### Update your local system - ``` bash + ```bash sudo apt update && sudo apt upgrade -y ``` @@ -40,19 +40,19 @@ If there is no `wireguard` package available for your system, you can follow the === "Raspberry Pi" - ``` bash + ```bash sudo apt install -y raspberrypi-kernel-headers libelf-dev build-essential pkg-config git ``` === "Linux" - ``` bash + ```bash sudo apt install -y linux-headers-$(uname -r) libelf-dev build-essential libmnl-dev git ``` ## Download and compile the `wireguard` module - ``` bash + ```bash git clone https://git.zx2c4.com/wireguard-linux-compat make -C wireguard-linux-compat/src -j$(nproc) sudo make -C wireguard-linux-compat/src install @@ -60,7 +60,7 @@ If there is no `wireguard` package available for your system, you can follow the You can ignore messages like - ``` plain + ```plain Warning: modules_install: missing 'System.map' file. Skipping depmod. ``` @@ -68,7 +68,7 @@ If there is no `wireguard` package available for your system, you can follow the Run - ``` bash + ```bash sudo modprobe wireguard ``` @@ -76,7 +76,7 @@ If there is no `wireguard` package available for your system, you can follow the ## Download and compile the `wireguard` tools (`wg`, etc.) - ``` bash + ```bash git clone https://git.zx2c4.com/wireguard-tools make -C wireguard-tools/src -j$(nproc) sudo make -C wireguard-tools/src install @@ -91,7 +91,7 @@ Each network interface has a private key and a list of peers. Each peer has a pu First, we create the folder containing our `wireguard` configuration: -``` bash +```bash sudo -i cd /etc/wireguard umask 077 @@ -101,7 +101,7 @@ umask 077 Inhere, we generate a key-pair for the server: -``` bash +```bash wg genkey | tee server.key | wg pubkey > server.pub ``` @@ -109,13 +109,13 @@ wg genkey | tee server.key | wg pubkey > server.pub Create a config file -``` bash +```bash sudo nano /etc/wireguard/wg0.conf ``` and put the following into it: -``` toml +```toml [Interface] Address = 10.100.0.1/24, fd08:4711::1/64 ListenPort = 47111 @@ -123,7 +123,7 @@ ListenPort = 47111 Then run -``` bash +```bash echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf exit # Exit the sudo session ``` @@ -138,7 +138,7 @@ If the server is behind NAT, be sure to forward the specified port on which Wire Register your server `wg0` as: -``` bash +```bash sudo systemctl enable wg-quick@wg0.service sudo systemctl daemon-reload sudo systemctl start wg-quick@wg0 @@ -150,7 +150,7 @@ If successful, you should not see any output. ??? warning "Error: RTNETLINK answers: Operation not supported" In case you get an error like - ``` plain + ```plain RTNETLINK answers: Operation not supported Unable to access interface: Protocol not supported ``` @@ -168,13 +168,13 @@ If successful, you should not see any output. With the following command, you can check if your `wireguard` server is running: -``` bash +```bash sudo wg ``` The output should look like the following: -``` plain +```plain interface: wg0 public key: XYZ123456ABC= ⬅ Your public key will be different private key: (hidden) From 5daa6b0e860c81c0b687fbc096c90112f20b8d77 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Wed, 21 Oct 2020 09:21:19 +0300 Subject: [PATCH 33/41] Minor grammar fixes --- docs/guides/wireguard/faq.md | 8 ++++---- docs/guides/wireguard/overview.md | 4 ++-- docs/guides/wireguard/route-everything.md | 4 ++-- docs/guides/wireguard/server.md | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md index 0ec039b6..916cd2dc 100644 --- a/docs/guides/wireguard/faq.md +++ b/docs/guides/wireguard/faq.md @@ -2,12 +2,12 @@ ## Issues with dynamic server IP -Host names cannot be resolved during startup. This may lead to a five minutes delay during boot. A solution to this is to disable the automatic start of the `wg` interface during start and connect only later (manually) when you are sure that you can resolve host names. +Hostnames cannot be resolved during startup. This may lead to a five minutes delay during boot. A solution to this is to disable the automatic start of the `wg` interface during start and connect only later (manually) when you are sure that you can resolve hostnames. 1. Disable `auto wg0` in `/etc/network/interfaces` (put `#` in front, like `#auto wg0`) 2. Start `wireguard` manually using `sudo ifup wg0` -If the IP changes while the connection is running, resolving the new IP address fails otten. Reconnect using +If the IP changes while the connection is running, resolving the new IP address fails often. Reconnect using ```bash sudo ifdown wg0 && sudo ifup wg0 @@ -63,7 +63,7 @@ unmanaged-devices=interface-name:wg* ## Broken DNS resolution -When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon new connection. This could be caused by a network manager or DHCP client overwriting `/etc/resolv.conf`. +When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon a new connection. This could be caused by a network manager or DHCP client overwriting `/etc/resolv.conf`. By default, `wg-quick` uses `resolvconf` to register new DNS entries (from the DNS keyword in the configuration file). This will cause issues with network managers and DHCP clients that do not use `resolvconf`, as they will overwrite `/etc/resolv.conf` thus removing the DNS servers added by `wg-quick`. The solution is to use networking software that supports `resolvconf`. @@ -75,7 +75,7 @@ The solution is to use networking software that supports `resolvconf`. ## Low MTU -Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client: +Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in the Interface section on the client: ```toml [Interface] diff --git a/docs/guides/wireguard/overview.md b/docs/guides/wireguard/overview.md index babbd8dd..b24eefe3 100644 --- a/docs/guides/wireguard/overview.md +++ b/docs/guides/wireguard/overview.md @@ -1,11 +1,11 @@ ### Remote accessing Pi-hole using WireGuard -WireGuard is an ***extremely simple yet fast and modern VPN*** that utilizes state-of-the-art cryptography. Comparing to other solutions, such as OpenVPN or IPsec, it aims to be **faster, simpler and leaner** while avoiding the massive overhead involved with other VPN solutions. +WireGuard is an ***extremely simple yet fast and modern VPN*** that utilizes state-of-the-art cryptography. Comparing to other solutions, such as OpenVPN or IPsec, it aims to be **faster, simpler, and leaner** while avoiding the massive overhead involved with other VPN solutions. A combination of extremely high-speed cryptographic primitives and the fact that WireGuard lives inside the Linux kernel means that secure networking can be very high-speed. It intends to be considerably more performant than OpenVPN. -WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many circumstances. +WireGuard is designed as a general-purpose VPN for running on embedded interfaces and super computers alike, fit for many circumstances. There is no need to manage connections, be concerned about state, manage daemons, or worry about what's under the hood. WireGuard presents an extremely basic yet powerful interface. diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index cd578a5a..7008234e 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -1,6 +1,6 @@ # Route the entire Internet traffic through the WireGuard tunnel -Routing your entire Internet traffic is **optional**, however, it can be advantageous in cases where you are expecting eavesdropping on the network. This may not only happen in unsecure open Wi-Fi networks (airports, hotels, trains, etc.) but also in encrypted Wi-Fi networks where the creator of the network can monitor client activity. +Routing your entire Internet traffic is **optional**, however, it can be advantageous in cases where you are expecting eavesdropping on the network. This may not only happen in insecure open Wi-Fi networks (airports, hotels, trains, etc.) but also in encrypted Wi-Fi networks where the creator of the network can monitor client activity. Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. @@ -25,6 +25,6 @@ AllowedIPs = 0.0.0.0/0, ::/0 Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. -That's all you need to do. You should use an online check (e.g. www.wieistmeineip.de) to check if your IP changed to the public IP address of your WireGuard server after this change up. It is possible to add this change only for a few clients, leaving the others without a full tunnel for all traffic (e.g., where this is not necessary or not desired). +That's all you need to do. You should use an online check (e.g. www.wieistmeineip.de) to check if your IP changed to the public IP address of your WireGuard server after this change. It is possible to add this change only for a few clients, leaving the others without a full tunnel for all traffic (e.g., where this is not necessary or not desired). {!abbreviations.md!} diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index af539bc2..9ffb9263 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -4,7 +4,7 @@ !!! info "The terms "server" and "client"" Usage of the terms `server` and `client` were purposefully chosen in this guide specifically to help both new users and existing OpenVPN users become familiar with the construction of WireGuard's configuration files. - WireGuard itself simply refers to all connected devices as `peers`. It consitutes a connection between computers. + WireGuard itself simply refers to all connected devices as `peers`. It constitutes a connection between computers. ## Installing the server components @@ -181,11 +181,11 @@ interface: wg0 listening port: 47111 ``` -Your public key will be different to ours. This is expected (you just created your own key above). +Your public key will be different from ours. This is expected (you just created your own key above). ## Set your Pi-hole to listen on all interfaces -On your [Settings page (tab DNS)](http://pi.hole/admin/settings.php?tab=dns), ensure you set the listing mode of your Pi-hole to one of the `Listen of all interfaces` settings. The top one is perferred as it adds a bit of additional safety. Your WireGuard peers/clients will be correctly recognized as being only one hop away. +On your [Settings page (tab DNS)](http://pi.hole/admin/settings.php?tab=dns), ensure you set the listing mode of your Pi-hole to one of the `Listen of all interfaces` settings. The top one is preferred as it adds a bit of additional safety. Your WireGuard peers/clients will be correctly recognized as being only one hop away. You can now continue to add clients. From c1853a9f8493a434fb1cb1d1f6e0264015fd9796 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 25 Oct 2020 20:25:44 +0100 Subject: [PATCH 34/41] Use bash instead of toml as syntax highlighting scheme for WireGuard configuration Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 4 ++-- docs/guides/wireguard/faq.md | 4 ++-- docs/guides/wireguard/internal.md | 14 +++++++------- docs/guides/wireguard/route-everything.md | 2 +- docs/guides/wireguard/server.md | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index cc476e3a..1b84c4b5 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -80,7 +80,7 @@ systemctl restart wg-quick@wg0 After a restart, the server file should look like: -```toml +```bash [Interface] Address = 10.100.0.1/24, fd08::1/128 ListenPort = 47111 @@ -132,7 +132,7 @@ echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf" Next, add your server as peer for this client: -```toml +```bash [Peer] AllowedIPs = 10.100.0.0/24, fd08::/64 Endpoint = [your public IP or domain]:47111 diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md index 916cd2dc..82132543 100644 --- a/docs/guides/wireguard/faq.md +++ b/docs/guides/wireguard/faq.md @@ -54,7 +54,7 @@ sudo crontab -e Users of NetworkManager should make sure that it is not managing the WireGuard interface(s). For example, create the configuration file `/etc/NetworkManager/conf.d/unmanaged.conf` with content -```toml +```bash [keyfile] unmanaged-devices=interface-name:wg* ``` @@ -77,7 +77,7 @@ The solution is to use networking software that supports `resolvconf`. Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in the Interface section on the client: -```toml +```bash [Interface] MTU = 1500 ``` diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 8884cf6e..7a22eba6 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -4,7 +4,7 @@ Enable IP forwarding on your server by removing the comments in front of -```toml +```bash net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 ``` @@ -19,8 +19,8 @@ sudo sysctl -p If you see the options repeated like -```plain -net.ipv4.ip_forward=1 +```bash +net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 ``` @@ -35,7 +35,7 @@ A properly configured firewall is ***highly*** recommended for any Internet-faci On your server, add the following to the `[INTERFACE]` section of your `/etc/wireguard/wg0.conf`: -```toml +```bash PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` @@ -55,14 +55,14 @@ In our standard configuration, we have configured the clients in such a way that Change the allowed addresses in your `/etc/wireguard/wg0.conf` from -```toml +```bash [Peer] AllowedIPs = 10.100.0.1/32, fd08:4711::1/64 ``` to -```toml +```bash [Peer] AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` @@ -73,7 +73,7 @@ assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254 Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature: -```toml +```bash [Peer] AllowedIPs = 10.0.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index 7008234e..5f69bf45 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -16,7 +16,7 @@ Rerouting the Internet traffic through your Pi-hole will furthermore cause all o To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your clients's WireGuard config files: -```toml +```bash AllowedIPs = 0.0.0.0/0, ::/0 ``` diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 9ffb9263..455af073 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -115,7 +115,7 @@ sudo nano /etc/wireguard/wg0.conf and put the following into it: -```toml +```bash [Interface] Address = 10.100.0.1/24, fd08:4711::1/64 ListenPort = 47111 From 053ee1e72db1187b8d2142c9f45bec27207dca43 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 1 Jan 2021 21:53:15 +0100 Subject: [PATCH 35/41] Improve guide by adding exemplary modified config files in the optional sections and remove the debated highlighting (use plain for all the Wireguard config files) Signed-off-by: DL6ER --- docs/guides/wireguard/client.md | 30 ++++---- docs/guides/wireguard/faq.md | 12 ++-- docs/guides/wireguard/internal.md | 85 +++++++++++++---------- docs/guides/wireguard/route-everything.md | 21 +++++- docs/guides/wireguard/server.md | 26 ++++--- 5 files changed, 107 insertions(+), 67 deletions(-) diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md index 1b84c4b5..66d353bd 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/wireguard/client.md @@ -6,7 +6,7 @@ For each new client, the following steps must be taken. For the sake of simplici ??? info "All commands described below at once" - ```bash + ``` bash sudo -i cd /etc/wireguard umask 077 @@ -40,7 +40,7 @@ For each new client, the following steps must be taken. For the sake of simplici We generate a key-pair for the client `NAME` (replace accordingly everywhere below): -```bash +``` bash sudo -i cd /etc/wireguard umask 077 @@ -52,7 +52,7 @@ wg genkey | tee "${name}.key" | wg pubkey > "${name}.pub" We furthermore recommend generating a pre-shared key (PSK) in addition to the keys above. This adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography and is mainly for post-quantum resistance. A pre-shared key should be generated for each peer pair and *should not be reused*. -```bash +``` bash wg genpsk > "${name}.psk" ``` @@ -60,7 +60,7 @@ wg genpsk > "${name}.psk" Add the new client by running the command: -```bash +``` bash echo "[Peer]" >> /etc/wireguard/wg0.conf echo "PublicKey = $(cat "${name}.pub")" >> /etc/wireguard/wg0.conf echo "PresharedKey = $(cat "${name}.psk")" >> /etc/wireguard/wg0.conf @@ -74,13 +74,13 @@ echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf Restart your server to load the new client config: -```bash +``` bash systemctl restart wg-quick@wg0 ``` After a restart, the server file should look like: -```bash +``` plain [Interface] Address = 10.100.0.1/24, fd08::1/128 ListenPort = 47111 @@ -97,13 +97,13 @@ AllowedIPs = 10.100.0.2/32, fd08:4711::2/128 The command -```bash +``` bash wg ``` should tell you about your new client: -```plain +``` plain interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) @@ -118,7 +118,7 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen Create a dedicated config file for your new client: -```bash +``` bash echo "[Interface]" > "${name}.conf" echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> "${name}.conf" # May need editing echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hole's IP @@ -126,13 +126,13 @@ echo "DNS = 10.100.0.1" >> "${name}.conf" # Your Pi-hol and add the private key of this client -```bash +``` bash echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf" ``` Next, add your server as peer for this client: -```bash +``` plain [Peer] AllowedIPs = 10.100.0.0/24, fd08::/64 Endpoint = [your public IP or domain]:47111 @@ -141,7 +141,7 @@ PersistentKeepalive = 25 Then add the public key of the server as well as the PSK for this connection: -```bash +``` bash echo "PublicKey = $(cat server.pub)" >> "${name}.conf" echo "PresharedKey = $(cat "${name}.psk")" >> "${name}.conf" exit @@ -166,7 +166,7 @@ That's it. You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: -```bash +``` bash sudo qrencode -t ansiutf8 -r "/etc/wireguard/${name}.conf" ``` @@ -180,13 +180,13 @@ After creating/copying the connection information over to your client, you may u You can check if your client successfully connected by, once again, running -```plain +``` bash sudo wg ``` on the server. It should show some traffic for your client if everything works: -```plain +``` plain interface: wg0 public key: XYZ123456ABC= ⬅ Your server's public key will be different private key: (hidden) diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md index 82132543..03198cdc 100644 --- a/docs/guides/wireguard/faq.md +++ b/docs/guides/wireguard/faq.md @@ -9,13 +9,13 @@ Hostnames cannot be resolved during startup. This may lead to a five minutes del If the IP changes while the connection is running, resolving the new IP address fails often. Reconnect using -```bash +``` bash sudo ifdown wg0 && sudo ifup wg0 ``` To achieve a permanent solution, one can install a `cron` job which restarts the connection automatically whenever a change is detected. This avoids excessive restarts of the interface. Example script (taken from [Ubuntuusers Wiki](https://wiki.ubuntuusers.de/WireGuard)): -```bash +``` bash #!/bin/bash # Check state of wg0 interface wgstatus=$(wg) @@ -42,11 +42,11 @@ fi Store this file as `/home/[user name]/wg-restart.sh` and add it to your `crontab`: -```bash +``` bash sudo crontab -e ``` -```plain +``` plain */10 * * * * bash /home/[user name]/wg-restart.sh # Runs the script every 10 minutes ``` @@ -54,7 +54,7 @@ sudo crontab -e Users of NetworkManager should make sure that it is not managing the WireGuard interface(s). For example, create the configuration file `/etc/NetworkManager/conf.d/unmanaged.conf` with content -```bash +``` bash [keyfile] unmanaged-devices=interface-name:wg* ``` @@ -77,7 +77,7 @@ The solution is to use networking software that supports `resolvconf`. Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in the Interface section on the client: -```bash +``` bash [Interface] MTU = 1500 ``` diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 7a22eba6..3efd9982 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -4,7 +4,7 @@ Enable IP forwarding on your server by removing the comments in front of -```bash +``` plain net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 ``` @@ -13,13 +13,13 @@ in the file `/etc/sysctl.d/99-sysctl.conf` Then apply the new option with the command below. -```bash +``` bash sudo sysctl -p ``` If you see the options repeated like -```bash +``` plain net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 ``` @@ -30,9 +30,6 @@ A properly configured firewall is ***highly*** recommended for any Internet-faci ## Enable NAT on the server -!!! info "Optional for NAT" - If the server is behind a router and receives traffic via NAT, these iptables rules are not needed. - On your server, add the following to the `[INTERFACE]` section of your `/etc/wireguard/wg0.conf`: ```bash @@ -40,43 +37,59 @@ PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w - PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` -!!! warning "Substitute interface" - Substitute `eth0` in the preceding lines to match the Internet-facing interface. +!!! warning "**Important:** Substitute interface" + **Without the correct interface name, this will not work!** -??? info "The `PostUp` and `PostDown` options" - `PostUp` and `PostDown` defines steps to be run after the interface is turned on or off, respectively. In this case, iptables is used to set Linux IP masquerade rules to allow all the clients to share the server’s IPv4 and IPv6 address. - The rules will then be cleared once the tunnel is down. + Substitute `eth0` in the preceding lines to match the Internet-facing interface. This may be `ens2p0` or similar on more recent Ubuntu versions (check, e.g., `ip a` for details about your local interfaces). + +`PostUp` and `PostDown` defines steps to be run after the interface is turned on or off, respectively. In this case, iptables is used to set Linux IP masquerade rules to allow all the clients to share the server’s IPv4 and IPv6 address. +The rules will then be cleared once the tunnel is down. + +??? info "Exemplary server config file with this change" + ``` plain + [Interface] + PrivateKey = [your server's private key] + Address = [Wireguard-internal IPs of the server, e.g. 10.100.0.1/24, fd08:4711::1/64] + ListenPort = 47111 + + PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE + PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp2s0 -j MASQUERADE + + # Android phone + [Peer] + PublicKey = [public key of this client] + PresharedKey = [pre-shared key of this client] + AllowedIPs = [Wireguard-internal IP of this client, e.g., 10.100.0.2/32, fd08:4711::2/128] + + # maybe more [Peer] sections for more clients + ``` + + The important change is the extra PostUp` and `PostDown` in the `[Interface]` section. ## Allow clients to access other devices -In our standard configuration, we have configured the clients in such a way that they can only speak to the server. This has to be changed on both the server and the clients. +In our standard configuration, we have configured the clients in such a way that they can only speak to the server. Add the network range of your local network in CIDR notation (e.g., `192.168.2.1 - 192.168.2.254` -> `192.168.2.0/24`) in the `[Peers]` section of all clients you want to have this feature: -### Server side - -Change the allowed addresses in your `/etc/wireguard/wg0.conf` from - -```bash -[Peer] -AllowedIPs = 10.100.0.1/32, fd08:4711::1/64 -``` - -to - -```bash -[Peer] -AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.2.0/24 -``` - -assuming your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. The change `10.100.0.1/32` to `10.100.0.0/24` also allows your WireGuard peers to see each other. - -### Client side - -Do the same you did above for the server also in the `[Interface]` section of all clients you want to have this feature: - -```bash +``` plain [Peer] AllowedIPs = 10.0.0.0/24, fd08:4711::/64, 192.168.2.0/24 ``` - It is possible to add this only for a few clients, leaving the others isolated to only the Pi-hole server itself. + +??? info "Exemplary client config file with this change" + ``` plain + [Interface] + PrivateKey = [your client's private key] + Address = [Wireguard-internal IPs of your client, e.g. 10.100.0.2/32, fd08:4711::2/128] + DNS = 10.100.0.1 + + [Peer] + AllowedIPs = 10.100.0.0/24, fd08::/64, 192.168.2.0/24 + Endpoint = [your server's public IP or domain]:47111 + PublicKey = [public key of the server] + PresharedKey = [pre-shared key of this client] + PersistentKeepalive = 25 + ``` + + The important change is the extra `192.168.2.0/24` at the end of the `[Peer] -> AllowedIPs` entry. diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index 5f69bf45..20483754 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -14,12 +14,29 @@ Rerouting the Internet traffic through your Pi-hole will furthermore cause all o The following assumes you have already prepared your Pi-hole for [IP forwarding](internal.md#enable-ip-forwarding-on-the-server) and [enabled NAT](internal.md#enable-nat-on-the-server). If this is not the case, follow the steps over there before continuing here. -To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your clients's WireGuard config files: +To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in the `[Peer]` section of your clients's WireGuard config files: -```bash +``` plain AllowedIPs = 0.0.0.0/0, ::/0 ``` +??? info "Exemplary client config file with this change" + ``` plain + [Interface] + PrivateKey = [your client's private key] + Address = [Wireguard-internal IPs of your client, e.g. 10.100.0.2/32, fd08:4711::2/128] + DNS = 10.100.0.1 + + [Peer] + AllowedIPs = 0.0.0.0/0, ::/0 + Endpoint = [your server's public IP or domain]:47111 + PublicKey = [public key of the server] + PresharedKey = [pre-shared key of this client] + PersistentKeepalive = 25 + ``` + + The important change is setting the `[Peer] -> AllowedIPs` entry to `0.0.0.0/0, ::/0` + !!! warning "Change this setting only on your clients" Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index 455af073..cc8e83bc 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -109,13 +109,13 @@ wg genkey | tee server.key | wg pubkey > server.pub Create a config file -```bash +``` bash sudo nano /etc/wireguard/wg0.conf ``` and put the following into it: -```bash +``` plain [Interface] Address = 10.100.0.1/24, fd08:4711::1/64 ListenPort = 47111 @@ -123,7 +123,7 @@ ListenPort = 47111 Then run -```bash +``` bash echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf exit # Exit the sudo session ``` @@ -138,7 +138,7 @@ If the server is behind NAT, be sure to forward the specified port on which Wire Register your server `wg0` as: -```bash +``` bash sudo systemctl enable wg-quick@wg0.service sudo systemctl daemon-reload sudo systemctl start wg-quick@wg0 @@ -150,31 +150,41 @@ If successful, you should not see any output. ??? warning "Error: RTNETLINK answers: Operation not supported" In case you get an error like - ```plain + ``` plain RTNETLINK answers: Operation not supported Unable to access interface: Protocol not supported ``` you should check that the WireGuard kernel module is loaded with the command below: - ```bash + ``` bash sudo modprobe wireguard ``` If you get an error saying the module is missing, try reinstalling WireGuard or restart your server and try again. This may happen when the WireGuard server is installed for a more recent kernel than you are currently running. This typically happens when you have neither updated nor restarted your system for a long time. + +??? warning "Error: RTNETLINK answers: File exists" + In case you get an error like + + ``` plain + RTNETLINK answers: File exists + ``` + + you need to check the configured IP addresses (check the CIDR notation). Overlapping IP address ranges cause this error when trying to register a router for an address where a a route already exists. This is meaningful and always an error in your configuration. However, the error message could be more clear about this. + ## Check everything is running With the following command, you can check if your `wireguard` server is running: -```bash +``` bash sudo wg ``` The output should look like the following: -```plain +``` plain interface: wg0 public key: XYZ123456ABC= ⬅ Your public key will be different private key: (hidden) From a5df3c5ed241b7a6c9f607716767a5951c455cd9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 2 Jan 2021 10:06:31 +0100 Subject: [PATCH 36/41] markdownlint changes Signed-off-by: DL6ER --- docs/guides/wireguard/internal.md | 11 ++++++++--- docs/guides/wireguard/route-everything.md | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md index 3efd9982..f361071a 100644 --- a/docs/guides/wireguard/internal.md +++ b/docs/guides/wireguard/internal.md @@ -37,24 +37,27 @@ PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w - PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` + !!! warning "**Important:** Substitute interface" **Without the correct interface name, this will not work!** Substitute `eth0` in the preceding lines to match the Internet-facing interface. This may be `ens2p0` or similar on more recent Ubuntu versions (check, e.g., `ip a` for details about your local interfaces). + `PostUp` and `PostDown` defines steps to be run after the interface is turned on or off, respectively. In this case, iptables is used to set Linux IP masquerade rules to allow all the clients to share the server’s IPv4 and IPv6 address. The rules will then be cleared once the tunnel is down. + ??? info "Exemplary server config file with this change" ``` plain [Interface] PrivateKey = [your server's private key] Address = [Wireguard-internal IPs of the server, e.g. 10.100.0.1/24, fd08:4711::1/64] ListenPort = 47111 - + PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp2s0 -j MASQUERADE - + # Android phone [Peer] PublicKey = [public key of this client] @@ -65,7 +68,7 @@ The rules will then be cleared once the tunnel is down. ``` The important change is the extra PostUp` and `PostDown` in the `[Interface]` section. - + ## Allow clients to access other devices In our standard configuration, we have configured the clients in such a way that they can only speak to the server. Add the network range of your local network in CIDR notation (e.g., `192.168.2.1 - 192.168.2.254` -> `192.168.2.0/24`) in the `[Peers]` section of all clients you want to have this feature: @@ -77,6 +80,7 @@ AllowedIPs = 10.0.0.0/24, fd08:4711::/64, 192.168.2.0/24 It is possible to add this only for a few clients, leaving the others isolated to only the Pi-hole server itself. + ??? info "Exemplary client config file with this change" ``` plain [Interface] @@ -93,3 +97,4 @@ It is possible to add this only for a few clients, leaving the others isolated t ``` The important change is the extra `192.168.2.0/24` at the end of the `[Peer] -> AllowedIPs` entry. + diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md index 20483754..6aa4d83a 100644 --- a/docs/guides/wireguard/route-everything.md +++ b/docs/guides/wireguard/route-everything.md @@ -20,6 +20,7 @@ To route all traffic through the tunnel to a specific peer, add the default rout AllowedIPs = 0.0.0.0/0, ::/0 ``` + ??? info "Exemplary client config file with this change" ``` plain [Interface] @@ -37,7 +38,6 @@ AllowedIPs = 0.0.0.0/0, ::/0 The important change is setting the `[Peer] -> AllowedIPs` entry to `0.0.0.0/0, ::/0` - !!! warning "Change this setting only on your clients" Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. From 8b137b49f0c7bff271461745adf5c50ad344bba5 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 4 Jan 2021 10:27:35 +0100 Subject: [PATCH 37/41] Add more description what NAT is Signed-off-by: DL6ER --- docs/abbreviations.md | 1 + docs/guides/wireguard/server.md | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/abbreviations.md b/docs/abbreviations.md index 31548b72..44e00078 100644 --- a/docs/abbreviations.md +++ b/docs/abbreviations.md @@ -38,3 +38,4 @@ *[SSH]: Secure Shell is a cryptographic network protocol for operating network services securely over an unsecured network *[TFTP]: Trivial File Transfer Protocol is a simple lockstep File Transfer Protocol which allows a client to get a file from or put a file onto a remote host *[TTL]: Time-To-Live is a mechanism that limits the lifespan or lifetime of data in a computer or network +*[NAT]: Network address translation diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index cc8e83bc..fe4ffa1c 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -132,7 +132,11 @@ to copy the server's private key into your config file. ## Forward port -If the server is behind NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `47111/UDP`) from the router to the WireGuard server. +If the server is behind a device, e.g., a router that is doing NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `47111/UDP`) from the router to the WireGuard server. + +??? info "NAT: Network address translation" + Network address translation modifies network packages. Incoming connection requests have their destination address rewritten to a different one. + NAT involves more than just changing the IP addresses. For instance, when mapping address `1.2.3.4` to `5.6.7.8`, there is no need to add a rule to do the reverse translation. A `netfilter` system called `conntrack` recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. Reverse translation is done automatically. ## Start the server From 7a3b000c29dc0d683b54dc164d5a07ccd4c530f1 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 4 Jan 2021 10:56:29 +0100 Subject: [PATCH 38/41] Add DynDNS recommendation/documentation Signed-off-by: DL6ER --- docs/abbreviations.md | 1 + docs/guides/wireguard/server.md | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/abbreviations.md b/docs/abbreviations.md index 44e00078..d4af635b 100644 --- a/docs/abbreviations.md +++ b/docs/abbreviations.md @@ -39,3 +39,4 @@ *[TFTP]: Trivial File Transfer Protocol is a simple lockstep File Transfer Protocol which allows a client to get a file from or put a file onto a remote host *[TTL]: Time-To-Live is a mechanism that limits the lifespan or lifetime of data in a computer or network *[NAT]: Network address translation +*[DnyDNS]: Dynamic DNS record pointing to a frequently changing IP address diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index fe4ffa1c..d5a6ed25 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -130,7 +130,7 @@ exit # Exit the sudo session to copy the server's private key into your config file. -## Forward port +## Forward port on your router If the server is behind a device, e.g., a router that is doing NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `47111/UDP`) from the router to the WireGuard server. @@ -138,6 +138,37 @@ If the server is behind a device, e.g., a router that is doing NAT, be sure to f Network address translation modifies network packages. Incoming connection requests have their destination address rewritten to a different one. NAT involves more than just changing the IP addresses. For instance, when mapping address `1.2.3.4` to `5.6.7.8`, there is no need to add a rule to do the reverse translation. A `netfilter` system called `conntrack` recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. Reverse translation is done automatically. +## Set up a domain name for your router + +When connecting from outside your network, you'll need to know the public IP address of your router to connect. However, as most households are getting dynamically-assigned public IP addresses (these addresses change periodically), you need to note down the address every day before leaving the house. Since this is obviously *very* uncomfortable, we strongly suggest registering a *dynamic host record* (often called "[DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)" record). + +There are many excellent guide and a lot of services offer this for free (with more or less comfort). We suggest a few providers below, however, this list is neither absolute nor exhaustive: + + +??? info "DynDNS providers" + - [Strato.de](https://www.strato.de/hosting/dynamic-dns-free/) (Guides: [EN](https://www.strato.com/faq/en_us/domain/this-is-how-easy-it-is-to-set-up-dyndns-for-your-domains/) / [DE](https://www.strato.de/faq/domains/so-einfach-richten-sie-dyndns-fuer-ihre-domains-ein/)) + + If you already have a hosting package at Strato, you can easily set up a subdomain to be used as DynDNS record. This is entirely free for members. + + - [DNSHome.de](DNSHome.de) + + This provider offers you several free subdomains under different domain names. SSL and also IPv6 are possible. DNSSEC is activated by default. They offer configuration guides for the Fritz!Box and also `ddclient` (update tool for Windows and Linux) on the website. + + - [GoIP.de](http://www.goip.de/) + + Go IP is a German DynDNS provider. The service is completely free and allows the registration of one domain and up to 15 subdomains per person. The website is characterized by extensive help with setting up the router. + + - [noip.com](https://www.noip.com/support/knowledgebase/getting-started-with-no-ip-com/) + + You can up to three hostnames like `myname.no-ip.org` for free. A disadvantage is that you have to confirm the domains at least every 30 days, otherwise they will be deleted. + + - [Dyn.com](https://account.dyn.com/) + + One of the first providers to offer DynDNS was the American company Dyn, whose product "DynDNS" gave its name to an entire service branch. In the meantime, numerous successors whose services are often free of charge came up. DynDNS service is especially easy to use is if it is directly supported by the router. + + +You can either use the methods the corresponding providers recommend or use existing DynDNS solutions inbuilt in your router (if available). Most providers are compatible with, e.g., the popular Fritz!Box routers ([EN](https://en.avm.de/service/fritzbox/fritzbox-4040/knowledge-base/publication/show/30_Setting-up-dynamic-DNS-in-the-FRITZ-Box/) / [DE](https://avm.de/service/fritzbox/fritzbox-7590/wissensdatenbank/publication/show/30_Dynamic-DNS-in-FRITZ-Box-einrichten/)). + ## Start the server Register your server `wg0` as: From af497e9fd95c276db1ee9b6bdf188982b121f34e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 4 Jan 2021 11:03:08 +0100 Subject: [PATCH 39/41] Suggest DELAY_STARTUP in the FAQ section Signed-off-by: DL6ER --- docs/guides/wireguard/faq.md | 10 ++++++++++ docs/guides/wireguard/server.md | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md index 03198cdc..f6d9689e 100644 --- a/docs/guides/wireguard/faq.md +++ b/docs/guides/wireguard/faq.md @@ -83,3 +83,13 @@ MTU = 1500 ``` [source](https://wiki.archlinux.org/index.php/WireGuard) + +## Pi-hole not listening on `wg0` after reboot + +If, e.g., after reboot, the `wg0` interface isn't up before Pi-hole is ready (more precisely, the `pihole-FTL` service is started), you may experience that Pi-hole doesn't listen on the Wireguard interface. This can be mitigated by artificially delaying the start of Pi-hole using, e.g., the config option + +``` plain +DELAY_STARTUP=5 +``` + +in `/etc/pihole/pihole-FTL.conf` to have Pi-hole delay the start of the DNS server by `5` seconds. diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index d5a6ed25..e1b1c6c6 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -150,11 +150,11 @@ There are many excellent guide and a lot of services offer this for free (with m If you already have a hosting package at Strato, you can easily set up a subdomain to be used as DynDNS record. This is entirely free for members. - - [DNSHome.de](DNSHome.de) + - [DNSHome.de](https://DNSHome.de) This provider offers you several free subdomains under different domain names. SSL and also IPv6 are possible. DNSSEC is activated by default. They offer configuration guides for the Fritz!Box and also `ddclient` (update tool for Windows and Linux) on the website. - - [GoIP.de](http://www.goip.de/) + - [GoIP.de](https://www.goip.de/) Go IP is a German DynDNS provider. The service is completely free and allows the registration of one domain and up to 15 subdomains per person. The website is characterized by extensive help with setting up the router. From 3bdc419a627ca9854e83d30f5cd09601fb5f31bc Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 4 Jan 2021 11:10:55 +0100 Subject: [PATCH 40/41] Minor grammar adjustments Signed-off-by: DL6ER --- docs/guides/wireguard/server.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md index e1b1c6c6..a8be67e3 100644 --- a/docs/guides/wireguard/server.md +++ b/docs/guides/wireguard/server.md @@ -136,19 +136,21 @@ If the server is behind a device, e.g., a router that is doing NAT, be sure to f ??? info "NAT: Network address translation" Network address translation modifies network packages. Incoming connection requests have their destination address rewritten to a different one. - NAT involves more than just changing the IP addresses. For instance, when mapping address `1.2.3.4` to `5.6.7.8`, there is no need to add a rule to do the reverse translation. A `netfilter` system called `conntrack` recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. Reverse translation is done automatically. + NAT involves more than just changing the IP addresses. For instance, when mapping address `1.2.3.4` to `5.6.7.8`, there is no need to add a rule to do the reverse translation. A `netfilter` system called `conntrack` recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. The reverse translation is done automatically. ## Set up a domain name for your router -When connecting from outside your network, you'll need to know the public IP address of your router to connect. However, as most households are getting dynamically-assigned public IP addresses (these addresses change periodically), you need to note down the address every day before leaving the house. Since this is obviously *very* uncomfortable, we strongly suggest registering a *dynamic host record* (often called "[DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)" record). +When connecting from outside your network, you'll need to know the public IP address of your router to connect. However, as most households are getting dynamically-assigned public IP addresses (these addresses change periodically), you need to note down the address every day before leaving the house. Since this is *very* uncomfortable, we strongly suggest registering a *dynamic host record* (often called "[DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)" record). -There are many excellent guide and a lot of services offer this for free (with more or less comfort). We suggest a few providers below, however, this list is neither absolute nor exhaustive: +The public IP address is checked at regular intervals. As soon as it changes, the router (or a DynDNS tool) sends a corresponding message to a URL of the service provider, who then updates the record. + +There are many excellent guides and a lot of services offer this for free (with more or less comfort). We suggest a few providers below, however, this list is neither absolute nor exhaustive: ??? info "DynDNS providers" - [Strato.de](https://www.strato.de/hosting/dynamic-dns-free/) (Guides: [EN](https://www.strato.com/faq/en_us/domain/this-is-how-easy-it-is-to-set-up-dyndns-for-your-domains/) / [DE](https://www.strato.de/faq/domains/so-einfach-richten-sie-dyndns-fuer-ihre-domains-ein/)) - If you already have a hosting package at Strato, you can easily set up a subdomain to be used as DynDNS record. This is entirely free for members. + If you already have a hosting package at Strato, you can easily set up a subdomain to be used as a DynDNS record. This is entirely free for members. - [DNSHome.de](https://DNSHome.de) From ba88c67c6920d296c3eb0048ae39f121d84d99f2 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 19 Jan 2021 10:11:14 +0100 Subject: [PATCH 41/41] Sort guids in subcategories Signed-off-by: DL6ER --- docs/core/pihole-command.md | 2 +- .../{dns-over-https.md => dns/cloudflared.md} | 2 +- docs/guides/{ => dns}/unbound.md | 4 +- .../{ => dns}/upstream-dns-providers.md | 0 docs/guides/{ => misc}/benchmark.md | 2 +- docs/guides/{ => misc}/tor/dnssec.md | 0 docs/guides/{ => misc}/tor/overview.md | 0 .../{ => misc}/tor/performance-issues.md | 0 docs/guides/{ => misc}/tor/setup.md | 0 docs/guides/{ => misc}/tor/using-tor.md | 0 docs/guides/{ => misc}/whitelist-blacklist.md | 0 .../vpn/{ => openvpn}/Android-Connected.png | Bin .../vpn/{ => openvpn}/Android-Import-1.png | Bin .../vpn/{ => openvpn}/Android-Import-2.png | Bin .../vpn/{ => openvpn}/Android-Import-3.png | Bin .../vpn/{ => openvpn}/Android-Import-4.png | Bin .../vpn/{ => openvpn}/Android-Pi-hole.png | Bin .../{ => openvpn}/Android-Transport-Error.png | Bin .../vpn/{ => openvpn}/NetworkManager1.png | Bin .../vpn/{ => openvpn}/NetworkManager2.png | Bin .../vpn/{ => openvpn}/NetworkManager3.png | Bin .../vpn/{ => openvpn}/NetworkManager4.png | Bin .../vpn/{ => openvpn}/NetworkManager5.png | Bin .../vpn/{ => openvpn}/NetworkManager6.png | Bin .../vpn/{ => openvpn}/NetworkManager7.png | Bin .../{ => openvpn}/Strato-DynDNS-Domain.png | Bin .../{ => openvpn}/Strato-DynDNS-Enable.png | Bin .../{ => openvpn}/Strato-DynDNS-Password.png | Bin docs/guides/vpn/{ => openvpn}/VPNclients.png | Bin .../guides/vpn/{ => openvpn}/VPNdashboard.png | Bin .../vpn/{ => openvpn}/android-client.md | 0 docs/guides/vpn/{ => openvpn}/client.ovpn | 0 docs/guides/vpn/{ => openvpn}/clients.md | 0 docs/guides/vpn/{ => openvpn}/dual-VPN.md | 0 .../vpn/{ => openvpn}/dual-operation.md | 0 docs/guides/vpn/{ => openvpn}/dynDNS.md | 0 docs/guides/vpn/{ => openvpn}/firewall.md | 0 docs/guides/vpn/{ => openvpn}/installation.md | 0 .../vpn/{ => openvpn}/listening-behavior.png | Bin .../vpn/{ => openvpn}/only-dns-via-vpn.md | 0 docs/guides/vpn/{ => openvpn}/overview.md | 0 .../vpn/{ => openvpn}/setup-openvpn-server.md | 0 .../vpn/{ => openvpn}/troubleshooting.md | 0 docs/guides/{ => vpn}/wireguard/client.md | 2 +- docs/guides/{ => vpn}/wireguard/concept.md | 0 docs/guides/{ => vpn}/wireguard/faq.md | 0 docs/guides/{ => vpn}/wireguard/internal.md | 0 docs/guides/{ => vpn}/wireguard/overview.md | 0 .../{ => vpn}/wireguard/route-everything.md | 0 docs/guides/{ => vpn}/wireguard/server.md | 0 .../caddy.md} | 0 .../nginx.md} | 0 .../traefik-nodocker.md} | 0 mkdocs.yml | 100 +++++++++++------- 54 files changed, 71 insertions(+), 41 deletions(-) rename docs/guides/{dns-over-https.md => dns/cloudflared.md} (99%) rename docs/guides/{ => dns}/unbound.md (99%) rename docs/guides/{ => dns}/upstream-dns-providers.md (100%) rename docs/guides/{ => misc}/benchmark.md (98%) rename docs/guides/{ => misc}/tor/dnssec.md (100%) rename docs/guides/{ => misc}/tor/overview.md (100%) rename docs/guides/{ => misc}/tor/performance-issues.md (100%) rename docs/guides/{ => misc}/tor/setup.md (100%) rename docs/guides/{ => misc}/tor/using-tor.md (100%) rename docs/guides/{ => misc}/whitelist-blacklist.md (100%) rename docs/guides/vpn/{ => openvpn}/Android-Connected.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Import-1.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Import-2.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Import-3.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Import-4.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Pi-hole.png (100%) rename docs/guides/vpn/{ => openvpn}/Android-Transport-Error.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager1.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager2.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager3.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager4.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager5.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager6.png (100%) rename docs/guides/vpn/{ => openvpn}/NetworkManager7.png (100%) rename docs/guides/vpn/{ => openvpn}/Strato-DynDNS-Domain.png (100%) rename docs/guides/vpn/{ => openvpn}/Strato-DynDNS-Enable.png (100%) rename docs/guides/vpn/{ => openvpn}/Strato-DynDNS-Password.png (100%) rename docs/guides/vpn/{ => openvpn}/VPNclients.png (100%) rename docs/guides/vpn/{ => openvpn}/VPNdashboard.png (100%) rename docs/guides/vpn/{ => openvpn}/android-client.md (100%) rename docs/guides/vpn/{ => openvpn}/client.ovpn (100%) rename docs/guides/vpn/{ => openvpn}/clients.md (100%) rename docs/guides/vpn/{ => openvpn}/dual-VPN.md (100%) rename docs/guides/vpn/{ => openvpn}/dual-operation.md (100%) rename docs/guides/vpn/{ => openvpn}/dynDNS.md (100%) rename docs/guides/vpn/{ => openvpn}/firewall.md (100%) rename docs/guides/vpn/{ => openvpn}/installation.md (100%) rename docs/guides/vpn/{ => openvpn}/listening-behavior.png (100%) rename docs/guides/vpn/{ => openvpn}/only-dns-via-vpn.md (100%) rename docs/guides/vpn/{ => openvpn}/overview.md (100%) rename docs/guides/vpn/{ => openvpn}/setup-openvpn-server.md (100%) rename docs/guides/vpn/{ => openvpn}/troubleshooting.md (100%) rename docs/guides/{ => vpn}/wireguard/client.md (98%) rename docs/guides/{ => vpn}/wireguard/concept.md (100%) rename docs/guides/{ => vpn}/wireguard/faq.md (100%) rename docs/guides/{ => vpn}/wireguard/internal.md (100%) rename docs/guides/{ => vpn}/wireguard/overview.md (100%) rename docs/guides/{ => vpn}/wireguard/route-everything.md (100%) rename docs/guides/{ => vpn}/wireguard/server.md (100%) rename docs/guides/{caddy-configuration.md => webserver/caddy.md} (100%) rename docs/guides/{nginx-configuration.md => webserver/nginx.md} (100%) rename docs/guides/{traefik-configuration-nodocker.md => webserver/traefik-nodocker.md} (100%) diff --git a/docs/core/pihole-command.md b/docs/core/pihole-command.md index d1d59fd1..a8e714cb 100644 --- a/docs/core/pihole-command.md +++ b/docs/core/pihole-command.md @@ -331,4 +331,4 @@ Help Command | `pihole -a interface --help` Script Location | [`/opt/pihole/webpage.sh`](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/webpage.sh) Example Usage | [`pihole -a interface local`](https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#interface) -Specify interface listening behavior for `pihole-FTL`. When using `pihole -a interface all`, please ensure you use a firewall to prevent your Pi-hole from becoming an unwitting host to [DNS amplification attackers](https://duckduckgo.com/?q=dns+amplification+attack). You may want to consider running [OpenVPN](../guides/vpn/overview.md) to grant your mobile devices access to the Pi-hole. +Specify interface listening behavior for `pihole-FTL`. When using `pihole -a interface all`, please ensure you use a firewall to prevent your Pi-hole from becoming an unwitting host to [DNS amplification attackers](https://duckduckgo.com/?q=dns+amplification+attack). You may want to consider running [Wireguard](../guides/vpn/wireguard/overview.md) to grant your mobile devices access to the Pi-hole. diff --git a/docs/guides/dns-over-https.md b/docs/guides/dns/cloudflared.md similarity index 99% rename from docs/guides/dns-over-https.md rename to docs/guides/dns/cloudflared.md index f5ee41f2..87782020 100644 --- a/docs/guides/dns-over-https.md +++ b/docs/guides/dns/cloudflared.md @@ -195,7 +195,7 @@ google.com. 191 IN A 172.217.22.14 Finally, configure Pi-hole to use the local `cloudflared` service as the upstream DNS server by specifying `127.0.0.1#5053` as the Custom DNS (IPv4): -![Screenshot of Pi-hole configuration](../images/DoHConfig.png) +![Screenshot of Pi-hole configuration](/images/DoHConfig.png) (don't forget to hit Return or click on `Save`) diff --git a/docs/guides/unbound.md b/docs/guides/dns/unbound.md similarity index 99% rename from docs/guides/unbound.md rename to docs/guides/dns/unbound.md index 6c31a520..019ed1db 100644 --- a/docs/guides/unbound.md +++ b/docs/guides/dns/unbound.md @@ -1,3 +1,5 @@ +## Pi-hole as All-Around DNS Solution + ### The problem: Whom can you trust? Pi-hole includes a caching and *forwarding* DNS server, now known as *FTL*DNS. After applying the blocking lists, it forwards requests made by the clients to configured upstream DNS server(s). However, as has been mentioned by several users in the past, this leads to some privacy concerns as it ultimately raises the question: _Whom can you trust?_ Recently, more and more small (and not so small) DNS upstream providers have appeared on the market, advertising free and private DNS service, but how can you know that they keep their promises? Right, you can't. @@ -156,7 +158,7 @@ The first command should give a status report of `SERVFAIL` and no IP address. T Finally, configure Pi-hole to use your recursive DNS server by specifying `127.0.0.1#5335` as the Custom DNS (IPv4): -![Upstream DNS Servers Configuration](../images/RecursiveResolver.png) +![Upstream DNS Servers Configuration](/images/RecursiveResolver.png) (don't forget to hit Return or click on `Save`) diff --git a/docs/guides/upstream-dns-providers.md b/docs/guides/dns/upstream-dns-providers.md similarity index 100% rename from docs/guides/upstream-dns-providers.md rename to docs/guides/dns/upstream-dns-providers.md diff --git a/docs/guides/benchmark.md b/docs/guides/misc/benchmark.md similarity index 98% rename from docs/guides/benchmark.md rename to docs/guides/misc/benchmark.md index 4560e3fc..c1d4ec17 100644 --- a/docs/guides/benchmark.md +++ b/docs/guides/misc/benchmark.md @@ -29,7 +29,7 @@ The long-term database can be disabled by setting DBFILE= ``` -in `/etc/pihole/pihole-FTL.conf` and running `sudo pihole restartdns` (see also [here](../ftldns/configfile.md#dbfile)). +in `/etc/pihole/pihole-FTL.conf` and running `sudo pihole restartdns` (see also [here](/ftldns/configfile/#dbfile)). ### 2.2 Increase DNS cache size diff --git a/docs/guides/tor/dnssec.md b/docs/guides/misc/tor/dnssec.md similarity index 100% rename from docs/guides/tor/dnssec.md rename to docs/guides/misc/tor/dnssec.md diff --git a/docs/guides/tor/overview.md b/docs/guides/misc/tor/overview.md similarity index 100% rename from docs/guides/tor/overview.md rename to docs/guides/misc/tor/overview.md diff --git a/docs/guides/tor/performance-issues.md b/docs/guides/misc/tor/performance-issues.md similarity index 100% rename from docs/guides/tor/performance-issues.md rename to docs/guides/misc/tor/performance-issues.md diff --git a/docs/guides/tor/setup.md b/docs/guides/misc/tor/setup.md similarity index 100% rename from docs/guides/tor/setup.md rename to docs/guides/misc/tor/setup.md diff --git a/docs/guides/tor/using-tor.md b/docs/guides/misc/tor/using-tor.md similarity index 100% rename from docs/guides/tor/using-tor.md rename to docs/guides/misc/tor/using-tor.md diff --git a/docs/guides/whitelist-blacklist.md b/docs/guides/misc/whitelist-blacklist.md similarity index 100% rename from docs/guides/whitelist-blacklist.md rename to docs/guides/misc/whitelist-blacklist.md diff --git a/docs/guides/vpn/Android-Connected.png b/docs/guides/vpn/openvpn/Android-Connected.png similarity index 100% rename from docs/guides/vpn/Android-Connected.png rename to docs/guides/vpn/openvpn/Android-Connected.png diff --git a/docs/guides/vpn/Android-Import-1.png b/docs/guides/vpn/openvpn/Android-Import-1.png similarity index 100% rename from docs/guides/vpn/Android-Import-1.png rename to docs/guides/vpn/openvpn/Android-Import-1.png diff --git a/docs/guides/vpn/Android-Import-2.png b/docs/guides/vpn/openvpn/Android-Import-2.png similarity index 100% rename from docs/guides/vpn/Android-Import-2.png rename to docs/guides/vpn/openvpn/Android-Import-2.png diff --git a/docs/guides/vpn/Android-Import-3.png b/docs/guides/vpn/openvpn/Android-Import-3.png similarity index 100% rename from docs/guides/vpn/Android-Import-3.png rename to docs/guides/vpn/openvpn/Android-Import-3.png diff --git a/docs/guides/vpn/Android-Import-4.png b/docs/guides/vpn/openvpn/Android-Import-4.png similarity index 100% rename from docs/guides/vpn/Android-Import-4.png rename to docs/guides/vpn/openvpn/Android-Import-4.png diff --git a/docs/guides/vpn/Android-Pi-hole.png b/docs/guides/vpn/openvpn/Android-Pi-hole.png similarity index 100% rename from docs/guides/vpn/Android-Pi-hole.png rename to docs/guides/vpn/openvpn/Android-Pi-hole.png diff --git a/docs/guides/vpn/Android-Transport-Error.png b/docs/guides/vpn/openvpn/Android-Transport-Error.png similarity index 100% rename from docs/guides/vpn/Android-Transport-Error.png rename to docs/guides/vpn/openvpn/Android-Transport-Error.png diff --git a/docs/guides/vpn/NetworkManager1.png b/docs/guides/vpn/openvpn/NetworkManager1.png similarity index 100% rename from docs/guides/vpn/NetworkManager1.png rename to docs/guides/vpn/openvpn/NetworkManager1.png diff --git a/docs/guides/vpn/NetworkManager2.png b/docs/guides/vpn/openvpn/NetworkManager2.png similarity index 100% rename from docs/guides/vpn/NetworkManager2.png rename to docs/guides/vpn/openvpn/NetworkManager2.png diff --git a/docs/guides/vpn/NetworkManager3.png b/docs/guides/vpn/openvpn/NetworkManager3.png similarity index 100% rename from docs/guides/vpn/NetworkManager3.png rename to docs/guides/vpn/openvpn/NetworkManager3.png diff --git a/docs/guides/vpn/NetworkManager4.png b/docs/guides/vpn/openvpn/NetworkManager4.png similarity index 100% rename from docs/guides/vpn/NetworkManager4.png rename to docs/guides/vpn/openvpn/NetworkManager4.png diff --git a/docs/guides/vpn/NetworkManager5.png b/docs/guides/vpn/openvpn/NetworkManager5.png similarity index 100% rename from docs/guides/vpn/NetworkManager5.png rename to docs/guides/vpn/openvpn/NetworkManager5.png diff --git a/docs/guides/vpn/NetworkManager6.png b/docs/guides/vpn/openvpn/NetworkManager6.png similarity index 100% rename from docs/guides/vpn/NetworkManager6.png rename to docs/guides/vpn/openvpn/NetworkManager6.png diff --git a/docs/guides/vpn/NetworkManager7.png b/docs/guides/vpn/openvpn/NetworkManager7.png similarity index 100% rename from docs/guides/vpn/NetworkManager7.png rename to docs/guides/vpn/openvpn/NetworkManager7.png diff --git a/docs/guides/vpn/Strato-DynDNS-Domain.png b/docs/guides/vpn/openvpn/Strato-DynDNS-Domain.png similarity index 100% rename from docs/guides/vpn/Strato-DynDNS-Domain.png rename to docs/guides/vpn/openvpn/Strato-DynDNS-Domain.png diff --git a/docs/guides/vpn/Strato-DynDNS-Enable.png b/docs/guides/vpn/openvpn/Strato-DynDNS-Enable.png similarity index 100% rename from docs/guides/vpn/Strato-DynDNS-Enable.png rename to docs/guides/vpn/openvpn/Strato-DynDNS-Enable.png diff --git a/docs/guides/vpn/Strato-DynDNS-Password.png b/docs/guides/vpn/openvpn/Strato-DynDNS-Password.png similarity index 100% rename from docs/guides/vpn/Strato-DynDNS-Password.png rename to docs/guides/vpn/openvpn/Strato-DynDNS-Password.png diff --git a/docs/guides/vpn/VPNclients.png b/docs/guides/vpn/openvpn/VPNclients.png similarity index 100% rename from docs/guides/vpn/VPNclients.png rename to docs/guides/vpn/openvpn/VPNclients.png diff --git a/docs/guides/vpn/VPNdashboard.png b/docs/guides/vpn/openvpn/VPNdashboard.png similarity index 100% rename from docs/guides/vpn/VPNdashboard.png rename to docs/guides/vpn/openvpn/VPNdashboard.png diff --git a/docs/guides/vpn/android-client.md b/docs/guides/vpn/openvpn/android-client.md similarity index 100% rename from docs/guides/vpn/android-client.md rename to docs/guides/vpn/openvpn/android-client.md diff --git a/docs/guides/vpn/client.ovpn b/docs/guides/vpn/openvpn/client.ovpn similarity index 100% rename from docs/guides/vpn/client.ovpn rename to docs/guides/vpn/openvpn/client.ovpn diff --git a/docs/guides/vpn/clients.md b/docs/guides/vpn/openvpn/clients.md similarity index 100% rename from docs/guides/vpn/clients.md rename to docs/guides/vpn/openvpn/clients.md diff --git a/docs/guides/vpn/dual-VPN.md b/docs/guides/vpn/openvpn/dual-VPN.md similarity index 100% rename from docs/guides/vpn/dual-VPN.md rename to docs/guides/vpn/openvpn/dual-VPN.md diff --git a/docs/guides/vpn/dual-operation.md b/docs/guides/vpn/openvpn/dual-operation.md similarity index 100% rename from docs/guides/vpn/dual-operation.md rename to docs/guides/vpn/openvpn/dual-operation.md diff --git a/docs/guides/vpn/dynDNS.md b/docs/guides/vpn/openvpn/dynDNS.md similarity index 100% rename from docs/guides/vpn/dynDNS.md rename to docs/guides/vpn/openvpn/dynDNS.md diff --git a/docs/guides/vpn/firewall.md b/docs/guides/vpn/openvpn/firewall.md similarity index 100% rename from docs/guides/vpn/firewall.md rename to docs/guides/vpn/openvpn/firewall.md diff --git a/docs/guides/vpn/installation.md b/docs/guides/vpn/openvpn/installation.md similarity index 100% rename from docs/guides/vpn/installation.md rename to docs/guides/vpn/openvpn/installation.md diff --git a/docs/guides/vpn/listening-behavior.png b/docs/guides/vpn/openvpn/listening-behavior.png similarity index 100% rename from docs/guides/vpn/listening-behavior.png rename to docs/guides/vpn/openvpn/listening-behavior.png diff --git a/docs/guides/vpn/only-dns-via-vpn.md b/docs/guides/vpn/openvpn/only-dns-via-vpn.md similarity index 100% rename from docs/guides/vpn/only-dns-via-vpn.md rename to docs/guides/vpn/openvpn/only-dns-via-vpn.md diff --git a/docs/guides/vpn/overview.md b/docs/guides/vpn/openvpn/overview.md similarity index 100% rename from docs/guides/vpn/overview.md rename to docs/guides/vpn/openvpn/overview.md diff --git a/docs/guides/vpn/setup-openvpn-server.md b/docs/guides/vpn/openvpn/setup-openvpn-server.md similarity index 100% rename from docs/guides/vpn/setup-openvpn-server.md rename to docs/guides/vpn/openvpn/setup-openvpn-server.md diff --git a/docs/guides/vpn/troubleshooting.md b/docs/guides/vpn/openvpn/troubleshooting.md similarity index 100% rename from docs/guides/vpn/troubleshooting.md rename to docs/guides/vpn/openvpn/troubleshooting.md diff --git a/docs/guides/wireguard/client.md b/docs/guides/vpn/wireguard/client.md similarity index 98% rename from docs/guides/wireguard/client.md rename to docs/guides/vpn/wireguard/client.md index 66d353bd..20842c80 100644 --- a/docs/guides/wireguard/client.md +++ b/docs/guides/vpn/wireguard/client.md @@ -201,7 +201,7 @@ peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be differen ## Test for DNS leaks -You should run a DNS leak test on [www.dnsleaktest.com](https://www.dnsleaktest.com) to ensure your WireGuard tunnel does not leak DNS requests (so all are processed by your Pi-hole). The expected outcome is that you should only see DNS servers belonging to the upstream DNS destination you selected in Pi-hole. If you configured [Pi-hole as All-Around DNS Solution](../unbound.md), you should only see the public IP address of your WireGuard server and no other DNS server. +You should run a DNS leak test on [www.dnsleaktest.com](https://www.dnsleaktest.com) to ensure your WireGuard tunnel does not leak DNS requests (so all are processed by your Pi-hole). The expected outcome is that you should only see DNS servers belonging to the upstream DNS destination you selected in Pi-hole. If you configured [Pi-hole as All-Around DNS Solution](/guides/dns/unbound/), you should only see the public IP address of your WireGuard server and no other DNS server. See also [What is a DNS leak and why should I care?](https://www.dnsleaktest.com/what-is-a-dns-leak.html) (external link). diff --git a/docs/guides/wireguard/concept.md b/docs/guides/vpn/wireguard/concept.md similarity index 100% rename from docs/guides/wireguard/concept.md rename to docs/guides/vpn/wireguard/concept.md diff --git a/docs/guides/wireguard/faq.md b/docs/guides/vpn/wireguard/faq.md similarity index 100% rename from docs/guides/wireguard/faq.md rename to docs/guides/vpn/wireguard/faq.md diff --git a/docs/guides/wireguard/internal.md b/docs/guides/vpn/wireguard/internal.md similarity index 100% rename from docs/guides/wireguard/internal.md rename to docs/guides/vpn/wireguard/internal.md diff --git a/docs/guides/wireguard/overview.md b/docs/guides/vpn/wireguard/overview.md similarity index 100% rename from docs/guides/wireguard/overview.md rename to docs/guides/vpn/wireguard/overview.md diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/vpn/wireguard/route-everything.md similarity index 100% rename from docs/guides/wireguard/route-everything.md rename to docs/guides/vpn/wireguard/route-everything.md diff --git a/docs/guides/wireguard/server.md b/docs/guides/vpn/wireguard/server.md similarity index 100% rename from docs/guides/wireguard/server.md rename to docs/guides/vpn/wireguard/server.md diff --git a/docs/guides/caddy-configuration.md b/docs/guides/webserver/caddy.md similarity index 100% rename from docs/guides/caddy-configuration.md rename to docs/guides/webserver/caddy.md diff --git a/docs/guides/nginx-configuration.md b/docs/guides/webserver/nginx.md similarity index 100% rename from docs/guides/nginx-configuration.md rename to docs/guides/webserver/nginx.md diff --git a/docs/guides/traefik-configuration-nodocker.md b/docs/guides/webserver/traefik-nodocker.md similarity index 100% rename from docs/guides/traefik-configuration-nodocker.md rename to docs/guides/webserver/traefik-nodocker.md diff --git a/mkdocs.yml b/mkdocs.yml index e3664b1a..ce1f2427 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -94,42 +94,46 @@ nav: - 'Contributing on GitHub': guides/github/contributing.md - 'How to sign-off commits': guides/github/how-to-signoff.md - 'Guides': - - 'Pi-hole as All-Around DNS Solution': guides/unbound.md - - 'WireGuard VPN': - - 'Overview': guides/wireguard/overview.md - - 'Concept': guides/wireguard/concept.md - - 'Install server': guides/wireguard/server.md - - 'Add client(s)': guides/wireguard/client.md - - 'Optional extra features': - - 'Make local devices accessible': guides/wireguard/internal.md - - 'Tunnel all Internet traffic': guides/wireguard/route-everything.md - - 'Troubleshooting': guides/wireguard/faq.md - - 'Configuring DNS-Over-HTTPS on Pi-hole': guides/dns-over-https.md - - 'Upstream DNS Providers': guides/upstream-dns-providers.md - - 'Editing Whitelist and Blacklist': guides/whitelist-blacklist.md - - 'Configuring NGINX for Pi-hole': guides/nginx-configuration.md - - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md - - 'Benchmarking': guides/benchmark.md - - 'Pi-hole and OpenVPN Server': - - 'Overview': guides/vpn/overview.md - - 'Installation': guides/vpn/installation.md - - 'Setup OpenVPN Server': guides/vpn/setup-openvpn-server.md - - 'Firewall Configuration': guides/vpn/firewall.md - - 'Connecting clients': - - 'General': guides/vpn/clients.md - - 'Android': guides/vpn/android-client.md - - 'Optional: Only route DNS via VPN': guides/vpn/only-dns-via-vpn.md - - 'Optional: Dual operation: LAN & VPN at the same time': guides/vpn/dual-operation.md - - 'Optional: Full and DNS-only': guides/vpn/dual-VPN.md - - 'Optional: Dynamic DNS': guides/vpn/dynDNS.md - - 'Troubleshooting': guides/vpn/troubleshooting.md - - 'Tor & Pi-hole': - - 'Overview': guides/tor/overview.md - - 'Basic Setup': guides/tor/setup.md - - 'Using Tor': guides/tor/using-tor.md - - 'Performance and other issues': guides/tor/performance-issues.md - - 'Using DNSSEC': guides/tor/dnssec.md + - 'DNS': + - 'unbound': guides/dns/unbound.md + - 'cloudflared (DoH)': guides/dns/cloudflared.md + - 'Upstream DNS Providers': guides/dns/upstream-dns-providers.md + - 'VPN': + - 'WireGuard': + - 'Overview': guides/vpn/wireguard/overview.md + - 'Concept': guides/vpn/wireguard/concept.md + - 'Install server': guides/vpn/wireguard/server.md + - 'Add client(s)': guides/vpn/wireguard/client.md + - 'Optional extra features': + - 'Make local devices accessible': guides/vpn/wireguard/internal.md + - 'Tunnel all Internet traffic': guides/vpn/wireguard/route-everything.md + - 'Troubleshooting': guides/vpn/wireguard/faq.md + - 'OpenVPN': + - 'Overview': guides/vpn/openvpn/overview.md + - 'Installation': guides/vpn/openvpn/installation.md + - 'Setup OpenVPN Server': guides/vpn/openvpn/setup-openvpn-server.md + - 'Firewall Configuration': guides/vpn/openvpn/firewall.md + - 'Connecting clients': + - 'General': guides/vpn/openvpn/clients.md + - 'Android': guides/vpn/openvpn/android-client.md + - 'Optional: Only route DNS via VPN': guides/vpn/openvpn/only-dns-via-vpn.md + - 'Optional: Dual operation: LAN & VPN at the same time': guides/vpn/openvpn/dual-operation.md + - 'Optional: Full and DNS-only': guides/vpn/openvpn/dual-VPN.md + - 'Optional: Dynamic DNS': guides/vpn/openvpn/dynDNS.md + - 'Troubleshooting': guides/vpn/openvpn/troubleshooting.md + - 'Misc': + - 'Benchmarking': guides/misc/benchmark.md + - 'Tor & Pi-hole': + - 'Overview': guides/misc/tor/overview.md + - 'Basic Setup': guides/misc/tor/setup.md + - 'Using Tor': guides/misc/tor/using-tor.md + - 'Performance and other issues': guides/misc/tor/performance-issues.md + - 'Using DNSSEC': guides/misc/tor/dnssec.md + - 'Whitelist and Blacklist editing': guides/misc/whitelist-blacklist.md + - 'Web server': + - 'NGINX': guides/webserver/nginx.md + - 'Caddy': guides/webserver/caddy.md + - 'Traefik (not in Docker)': guides/webserver/traefik-nodocker.md - 'Router setup': - 'Fritz!Box (EN)': routers/fritzbox.md - 'Fritz!Box (DE)': routers/fritzbox-de.md @@ -156,3 +160,27 @@ plugins: 'ftldns/regex/index.md': ftldns/regex/overview.md 'main/presentations.md': index.md 'main/prerequesites.md': main/prerequisites.md + 'guides/unbound.md': guides/dns/unbound.md + 'guides/upstream-dns-providers.md': guides/dns/upstream-dns-providers.md + 'guides/dns-over-https.md': guides/dns/cloudflared.md + 'guides/vpn/overview.md': guides/vpn/openvpn/overview.md + 'guides/vpn/installation.md': guides/vpn/openvpn/installation.md + 'guides/vpn/setup-openvpn-server.md': guides/vpn/openvpn/setup-openvpn-server.md + 'guides/vpn/firewall.md': guides/vpn/openvpn/firewall.md + 'guides/vpn/clients.md': guides/vpn/openvpn/clients.md + 'guides/vpn/android-client.md': guides/vpn/openvpn/android-client.md + 'guides/vpn/only-dns-via-vpn.md': guides/vpn/openvpn/only-dns-via-vpn.md + 'guides/vpn/dual-operation.md': guides/vpn/openvpn/dual-operation.md + 'guides/vpn/dual-VPN.md': guides/vpn/openvpn/dual-VPN.md + 'guides/vpn/dynDNS.md': guides/vpn/openvpn/dynDNS.md + 'guides/vpn/troubleshooting.md': guides/vpn/openvpn/troubleshooting.md + 'guides/benchmark.md': guides/misc/benchmark.md + 'guides/tor/overview.md': guides/misc/tor/overview.md + 'guides/tor/setup.md': guides/misc/tor/setup.md + 'guides/tor/using-tor.md': guides/misc/tor/using-tor.md + 'guides/tor/performance-issues.md': guides/misc/tor/performance-issues.md + 'guides/tor/dnssec.md': guides/misc/tor/dnssec.md + 'guides/whitelist-blacklist.md': guides/misc/whitelist-blacklist.md + 'guides/nginx-configuration.md': 'guides/webserver/nginx.md' + 'guides/caddy-configuration.md': 'guides/webserver/caddy.md' + 'guides/traefik-configuration-nodocker.md': 'guides/webserver/traefik-nodocker.md'