Merge branch 'master' into tweak/cache_size

This commit is contained in:
Adam Warner
2021-01-19 09:40:34 +00:00
committed by GitHub
67 changed files with 1228 additions and 419 deletions
+2
View File
@@ -38,3 +38,5 @@
*[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
*[DnyDNS]: Dynamic DNS record pointing to a frequently changing IP address
+1 -1
View File
@@ -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.
@@ -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`)
@@ -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`)
@@ -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

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

+208
View File
@@ -0,0 +1,208 @@
# 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.
<!-- markdownlint-disable code-block-style -->
??? 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
```
<!-- markdownlint-disable code-block-style -->
## Key generation
We generate a key-pair for the client `NAME` (replace accordingly everywhere below):
``` bash
sudo -i
cd /etc/wireguard
umask 077
name="client_name"
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 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 "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> /etc/wireguard/wg0.conf
```
<!-- markdownlint-disable code-block-style -->
!!! info "Client IP address"
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)
<!-- markdownlint-disable code-block-style -->
Restart your server to load the new client config:
``` bash
systemctl restart wg-quick@wg0
```
After a restart, the server file should look like:
``` plain
[Interface]
Address = 10.100.0.1/24, fd08::1/128
ListenPort = 47111
SaveConfig = true
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, fd08:4711::2/128
# 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: 47111
peer: F+80gbmHVlOrU+es13S18oMEX2g= ⬅ Your peer's public key will be different
preshared key: (hidden)
allowed ips: 10.100.0.2/32, fd08::2/128
```
## Create client configuration
Create a dedicated config file for your new client:
``` 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
```
and add the private key of this client
``` bash
echo "PrivateKey = $(cat "${name}.key")" >> "${name}.conf"
```
Next, add your server as peer for this client:
``` plain
[Peer]
AllowedIPs = 10.100.0.0/24, fd08::/64
Endpoint = [your public IP or domain]:47111
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"
exit
```
That's it.
<!-- markdownlint-disable code-block-style -->
??? 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.
<!-- markdownlint-disable code-block-style -->
## 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
sudo qrencode -t ansiutf8 -r "/etc/wireguard/${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
``` bash
sudo 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: 47111
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
```
## 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](/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).
{!abbreviations.md!}
+32
View File
@@ -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.
+95
View File
@@ -0,0 +1,95 @@
# Frequently asked questions
## Issues with dynamic server IP
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 often. 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
``` bash
[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 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`.
!!! 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 the Interface section on the client:
``` bash
[Interface]
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.
+100
View File
@@ -0,0 +1,100 @@
# Access internal devices through the WireGuard tunnel
## Enable IP forwarding on the server
Enable IP forwarding on your server by removing the comments in front of
``` plain
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
net.ipv6.conf.all.forwarding = 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
On your server, add the following to the `[INTERFACE]` section of your `/etc/wireguard/wg0.conf`:
```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
```
<!-- markdownlint-disable code-block-style -->
!!! 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).
<!-- markdownlint-enable code-block-style -->
`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 servers IPv4 and IPv6 address.
The rules will then be cleared once the tunnel is down.
<!-- markdownlint-disable code-block-style -->
??? 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.
<!-- markdownlint-enable code-block-style -->
## 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:
``` 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.
<!-- markdownlint-disable code-block-style -->
??? 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.
<!-- markdownlint-enable code-block-style -->
+30
View File
@@ -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!}
@@ -0,0 +1,47 @@
# 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 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.
<!-- markdownlint-disable code-block-style -->
!!! 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.).
<!-- markdownlint-enable code-block-style -->
<!-- markdownlint-disable code-block-style -->
!!! 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.
<!-- markdownlint-enable code-block-style -->
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:
``` plain
AllowedIPs = 0.0.0.0/0, ::/0
```
<!-- markdownlint-disable code-block-style -->
??? 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.
<!-- markdownlint-enable code-block-style -->
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!}
+239
View File
@@ -0,0 +1,239 @@
# Installing the WireGuard server
<!-- markdownlint-disable code-block-style -->
!!! 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 constitutes a connection between computers.
<!-- markdownlint-enable code-block-style -->
## 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
```
If there is no `wireguard` package available for your system, you can follow the instructions below to compile WireGuard from source.
<!-- markdownlint-disable code-block-style -->
??? info "Compile 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
```
### 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
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)
<!-- markdownlint-enable code-block-style -->
## 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:
``` plain
[Interface]
Address = 10.100.0.1/24, fd08:4711::1/64
ListenPort = 47111
```
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.
## 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.
??? 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. 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 *very* uncomfortable, we strongly suggest registering a *dynamic host record* (often called "[DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)" record).
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:
<!-- markdownlint-disable code-block-style -->
??? 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 a DynDNS record. This is entirely free for members.
- [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](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.
- [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.
<!-- markdownlint-enable code-block-style -->
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:
``` bash
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.
<!-- markdownlint-disable code-block-style -->
??? warning "Error: RTNETLINK answers: Operation not supported"
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.
??? 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.
<!-- markdownlint-enable code-block-style -->
## Check everything is running
With the following command, you can check if your `wireguard` server is running:
``` bash
sudo 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: 47111
```
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 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.
{!abbreviations.md!}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+92
View File
@@ -0,0 +1,92 @@
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.
### Erweiterte Ansicht aktivieren
Einige dieser Einstellungen sind nur sichtbar, wenn voher die Ansicht auf "Erweitert" gesetzt wurde. Diese wird durch Umschalten (Klick) auf "Standard" am unteren linken Bildrand aktiviert.
![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-advanced-de.png)
## 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 von der Fritz!Box anfordern.
DNS Anfragen nehmen folgenden Weg
```bash
Client -> Pi-hole -> Upstream DNS Server
```
> Hinweis:
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
```bash
Heimnetz/Netzwerk/Netzwerkeinstellungen/IP-Adressen/IPv4-Konfiguration/Heimnetz
```
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 sollten einzelne Clients in Pi-hole Dashboard auftrauchen.
## Pi-hole als Upstream DNS Server der Fritz!Box (WAN Seite)
Mit dieser Konfiguration wird Pi-hole auch von der Fritz!Box selbst als Upstream DNS Server genutzt. DNS Anfragen nehmen folgenden Weg
```bash
(Clients) -> Fritz!Box -> Pi-hole -> Upstream DNS Server
```
Zum Einstellen muss die IP des Pi-hole als "Bevorzugter DNSv4-Server" **und** "Alternativer DNSv4-Server" in
```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
```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 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)
+88
View File
@@ -0,0 +1,88 @@
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.
### Enable advanced settings
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.
![Screenshot der Fritz!Box DHCP Einstellungen](../images/fritzbox-advanced.png)
## 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 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 (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
```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 acquired a new DHCP lease. The easiest way to force a renewal is to dis/reconnect the client from the network.
Now you should see individual clients in Pi-hole's web dashboard.
## 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
(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 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.
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).
### 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. 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)
+70 -27
View File
@@ -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
@@ -91,33 +94,49 @@ 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
- '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
- 'Community Projects': main/projects.md
extra:
@@ -141,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'
+216 -385
View File
@@ -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": {
@@ -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"
}
},
@@ -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": {
@@ -214,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",
@@ -299,6 +273,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 +339,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 +430,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 +443,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 +515,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 +525,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 +576,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 +612,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,10 +650,19 @@
"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",
"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"
@@ -709,21 +677,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 +687,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,18 +745,18 @@
}
},
"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": {
"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",
@@ -882,25 +829,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 +846,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 +854,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 +1024,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 +1069,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 +1096,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",
@@ -1235,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",
@@ -1248,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"
@@ -1280,21 +1180,21 @@
}
},
"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": {
"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 +1204,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 +1238,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 +1292,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 +1322,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 +1427,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 +1453,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 +1499,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 +1521,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 +1601,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 +1660,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 +1686,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 +1708,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",
@@ -1882,18 +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
},
"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 +1792,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 +1846,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 +1882,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 +1913,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",
+2 -2
View File
@@ -22,7 +22,7 @@
"test": "npm run markdownlint && npm run linkinator"
},
"devDependencies": {
"linkinator": "^2.8.0",
"markdownlint-cli2": "0.0.11"
"linkinator": "^2.13.0",
"markdownlint-cli2": "0.0.13"
}
}
+1 -1
View File
@@ -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