diff --git a/README.md b/README.md
index 878bae8..19a2fb9 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,10 @@ You will need:
git clone https://github.com/enclave-networks/internet-gateway.git
```
+1. Customise your DNS block page (`./template/blockpage/index.html`) as required
+
+ 
+
1. Install Enclave, Docker, and other dependencies
```bash
@@ -169,25 +173,32 @@ Done
If changes are accidentally made to any of these policies in the future, running the `configure-tenant.ps1` script again will attempt to automatically detect the drift and refresh the correct configuration into the tenant.
-## Testing and installing root certificate
+## Testing
+
+Once your Internet Gateways are configured, you'll need to test them to ensure everything is working properly. This setup will have created three new Tags in your tenant:
+
+- `[internet-gateway]` - Applied to the Internet Gateways themselves (automatically configured)
+- `[internet-gateway-user]` - Apply this to end-user systems that should route traffic, DNS queries, or both through the Gateways
+- `[internet-gateway-admin]` - Apply this to administrator systems for management access to the PiHole Admin interface
-There are three new Tags in the tenant:
+Enrol a system to the tenant and attach the `[internet-gateway-admin]` tag to that system for testing. With your admin-tagged system, you should now be able to access the PiHole administration interface:
-- `[internet-gateway]` - Applied to the Internet Gateways themselves.
-- `[internet-gateway-user]` - Should be applied to end-users.
-- `[internet-gateway-admin]` - A special tag for Internet Gateway administrators only.
+- **Load-balanced URL**: [http://dnsfilter.enclave](http://dnsfilter.enclave)
-Enrol yourself to the tenant and attach the `[internet-gateway-admin]` tag to your system. You'll now be able to access [http://dnsfilter.enclave](http://dnsfilter.enclave) - the PiHole administration interface.
+- **Direct access URLs** (for troubleshooting):
+ - Primary gateway: http://100.64.0.2:1080/
+ - Secondary gateway: http://100.64.0.3:1080/
+## Installing Root Certificates
-We recommend downloading and installing the Gateway's Root Certificate so your browser can trust the block page ([https://blocked.enclave/](https://blocked.enclave/)).
+We recommend downloading and installing the Gateway's Root Certificate so your browser can trust the block page (served from [https://blocked.enclave/](https://blocked.enclave/)).
Download the Internet Gateway CA's public certificate in the appropriate format for yourself and end-users:
- http://dnsfilter.enclave/gateway.crt
- http://dnsfilter.enclave/gateway.p7b
-On Windows, use the `certmgr` tool to install `gateway.crt` into the `Trusted Root Certification Authorities` store using the `LOCAL COMPUTER` scope and restart your browser. Navigate to [http://dnsfilter.enclave](http://dnsfilter.enclave) and check you don't receive any certificate warnings.
+On Windows, use the `certmgr` tool to install `gateway.crt` into the `Trusted Root Certification Authorities` store using the `LOCAL COMPUTER` scope and restart your browser. Test by visiting [http://dnsfilter.enclave](http://dnsfilter.enclave) - you shouldn't receive any certificate warnings.
To test if your network traffic is successfully routing through the Internet Gateway, check your external IP address and then apply the `[internet-gateway-user]` tag to your system. Your Internet traffic should now be routing through the Internet Gateways and your external IP address should have changed to present as that of the primary Internet Gateway.
@@ -195,10 +206,16 @@ To test if your network traffic is successfully routing through the Internet Gat
## Operational notes
-- Failover between gateways is automatic. If one fails or goes offline, connected systems will automatically switch.
-- You may need to disable `Use secure DNS` in Chrome (`chrome://settings/security`) to stop it sending DNS queries directly to Google nameservers.
-- Notice the `300M` docker [memory limit](https://github.com/enclave-networks/internet-gateway/blob/main/template/docker-compose.primary.yml#L13) applied to the Enclave container and increase as required.
-- Only make PiHole configuration changes on the _primary_ gateway as the PiHole configuration in [synced](https://github.com/enclave-networks/internet-gateway/blob/main/template/docker-compose.primary.yml#L124) _from_ the primary to the secondary every 30 minutes.
+- Failover between gateways is automatic.
+- If one gateway fails or goes offline, connected systems will immediately and automatically switch to the partner.
+- When the primary gateway recovers, connected systems will automatically fail back to it.
+- You may need to disable `Use secure DNS` in Chrome (`chrome://settings/security`) to stop Chrome sending DNS queries directly to Google nameservers and bypassing DNS.
+- Only make PiHole configuration changes on the _primary_ gateway as the PiHole configuration in [synced](https://github.com/enclave-networks/internet-gateway/blob/main/template/docker-compose.primary.yml#L124) _from_ the primary to the secondary every minute.
+- Any changes made to the secondary gateway will be destroyed during the next sync from the primary.
+- Notice the `300M` docker [memory limit](https://github.com/enclave-networks/internet-gateway/blob/main/template/docker-compose.primary.yml#L13) applied to the Enclave container. Monitor and increase if necessary.
+- To bring the stack down: `sudo docker compose down`
+- To bring the stack up with latest images: `sudo docker compose up -d --pull always`
+- To rename the stack, edit `COMPOSE_PROJECT_NAME=` variable in `.env`
## Inspection
@@ -212,7 +229,7 @@ sudo iptables -t nat -L POSTROUTING -v -n
### Uninstall
-!!! Warning: Read these commands **BEFORE** you run them. If you don't understand exactly what they will do, contact us on our support channels for assistance.
+!!! Warning: Read these commands **BEFORE** you run them. If you don't understand exactly what they will do, contact our support channels for assistance.
```bash
sudo docker stop $(sudo docker ps -q) && sudo docker rm $(sudo docker ps -aq)
diff --git a/blockpage-example.png b/blockpage-example.png
new file mode 100644
index 0000000..508a045
Binary files /dev/null and b/blockpage-example.png differ
diff --git a/configure-tenant.ps1 b/configure-tenant.ps1
index 34f0d10..ea79e8a 100644
--- a/configure-tenant.ps1
+++ b/configure-tenant.ps1
@@ -256,7 +256,12 @@ $policiesModel = @(
@{
protocol = "Tcp"
ports = "444"
- description = "PiHole"
+ description = "Load-balanced access to PiHole admin dashboard"
+ },
+ @{
+ protocol = "Tcp"
+ ports = "1080"
+ description = "Direct access to PiHole dashboard"
},
@{
protocol = "Icmp"
@@ -300,15 +305,10 @@ $policiesModel = @(
"internet-gateway"
)
acls = @(
- @{
- protocol = "Udp"
- ports = "53"
- description = "DNS"
- },
@{
protocol = "Tcp"
- ports = "9999"
- description = "PiHole Gravity Database Sync"
+ ports = "1080"
+ description = "PiHole API Configuration Sync"
},
@{
protocol = "Icmp"
@@ -347,7 +347,7 @@ if ($HasEnrolledGateways -eq $true)
gateways = @()
gatewayTrafficDirection = "Exit"
gatewayAllowedIpRanges = @()
- gatewayPriority = "Balanced"
+ gatewayPriority = "Ordered"
}
if ($HasPrimaryGateway -eq $true)
diff --git a/template/blockpage/index.html b/template/blockpage/index.html
index a324567..9342bc8 100644
--- a/template/blockpage/index.html
+++ b/template/blockpage/index.html
@@ -1,22 +1,127 @@
+
-
-
-
This site has been blocked by your administrator.
-
Contact your administrator to request an exception.
+
+
Access Blocked
+
+
+
+
+
This site isn't accessible right now.
+
Content filtering is actively protecting our network, and this website has been identified as inappropriate, potentially unsafe, or malicious.
+
+
+
Need to request access?
+
+ - Raise a support ticket with the blocked website URL
+ - Include your business justification for needing access
+ - Tickets are typically reviewed within 24 hours
+
+
+
+
+
+ To request access to this site, please raise a ticket at
https://example.com
+
-
+
+
\ No newline at end of file
diff --git a/template/caddy/Caddyfile b/template/caddy/Caddyfile
index d2982ed..9ff25c7 100644
--- a/template/caddy/Caddyfile
+++ b/template/caddy/Caddyfile
@@ -10,11 +10,13 @@
}
}
+# Redirect all plain HTTP to blocked page
http:// {
bind {$PIHOLE_PROXY_BIND_ADDR}
redir http://blocked.enclave
}
+# Serve cert files over HTTP
http://dnsfilter.enclave {
bind {$PIHOLE_PROXY_BIND_ADDR}
route {
@@ -28,11 +30,38 @@ http://dnsfilter.enclave {
header * Content-Disposition "attachment"
file_server
}
+ redir * https://{host}/admin/
+ }
+}
+
+# Catch-all HTTPS handler for certs, blocked page, and redirects
+https:// {
+ bind {$PIHOLE_PROXY_BIND_ADDR}
+ tls internal {
+ on_demand
+ }
- redir * https://{host}
+ @dnsfilter host dnsfilter.enclave
+ handle @dnsfilter {
+ redir * https://{host}:444/admin
+ }
+
+ @blocked host blocked.enclave
+ handle @blocked {
+ header {
+ X-Frame-Options "DENY"
+ }
+ root * /blockpage
+ file_server
+ }
+
+ # Default fallback for all other HTTPS access
+ handle {
+ redir https://blocked.enclave
}
}
+# Load-balanced access to pihole admin dashboard. Always targets the primary first as config is replicated.
https://dnsfilter.enclave:444 {
bind {$PIHOLE_PROXY_BIND_ADDR}
tls internal
@@ -47,40 +76,3 @@ https://dnsfilter.enclave:444 {
fail_duration 30s
}
}
-
-# This is the 'end' of the chain; and points at the actual running pihole instance on the local host.
-http://:9999 {
- bind {$PIHOLE_PROXY_BIND_ADDR}
-
- reverse_proxy http://localhost:1080
- rewrite * /admin/{path}
-}
-
-https:// {
-
- bind {$PIHOLE_PROXY_BIND_ADDR}
-
- tls internal {
- on_demand
- }
-
- @dnsfilter host dnsfilter.enclave
-
- handle @dnsfilter {
- redir * https://{host}:444
- }
-
- @blocked host blocked.enclave
-
- handle @blocked {
- header {
- X-Frame-Options "DENY"
- }
- root * /blockpage
- file_server
- }
-
- handle {
- redir https://blocked.enclave
- }
-}
\ No newline at end of file
diff --git a/template/docker-compose.primary.yml b/template/docker-compose.primary.yml
index b8b2fec..db69967 100644
--- a/template/docker-compose.primary.yml
+++ b/template/docker-compose.primary.yml
@@ -41,7 +41,9 @@ services:
- ./etc/pihole:/etc/pihole
- etc-dnsmasq:/etc/dnsmasq.d
hostname: ${PIHOLE_HOSTNAME}
- mem_limit: 150M
+ # mem_limit: 300M
+ cap_add:
+ - CAP_SYS_TIME
restart: unless-stopped
ports:
- "${ENCLAVE_LOCAL_PORT}:${ENCLAVE_LOCAL_PORT}/tcp"
@@ -54,19 +56,16 @@ services:
gw-net:
environment:
TZ: 'Europe/London'
- WEBPASSWORD: ''
- WEB_PORT: 1080
- # Traffic to the pihole admin interface is
- # proxied through caddy (to apply HTTPS and handle redirects).
- # Restrict the web interface to only be available via that proxy.
- WEB_BIND_ADDR: 127.0.0.1
- CORS_HOSTS: dnsfilter.enclave
- DNSMASQ_LISTENING: all
- FTLCONF_LOCAL_IPV4: ${ENCLAVE_VIRTUAL_IP}
- FTLCONF_BLOCK_IPV4: ${ENCLAVE_VIRTUAL_IP}
- FTLCONF_BLOCKINGMODE: IP-NODATA-AAAA
- FTLCONF_PIHOLE_PTR: NONE
- FTLCONF_MAXDBDAYS: 30
+ FTLCONF_webserver_api_password: ''
+ FTLCONF_webserver_port: 1080
+ FTLCONF_dns_interface: '127.0.0.1'
+ FTLCONF_dns_domain: 'dnsfilter.enclave'
+ FTLCONF_dns_piholePTR: NONE
+ FTLCONF_dns_listeningMode: all
+ FTLCONF_dns_blocking_mode: IP_NODATA_AAAA
+ FTLCONF_dns_reply_host_IPv4: ${ENCLAVE_VIRTUAL_IP}
+ FTLCONF_dns_reply_blocking_IPv4: ${ENCLAVE_VIRTUAL_IP}
+ FTLCONF_database_maxDBdays: 30
pihole-enclave-sync:
image: enclavenetworks/pihole-enclave-sync:latest
@@ -101,11 +100,11 @@ services:
cpu_count: 1
environment:
PIHOLE_PROXY_BIND_ADDR: ${ENCLAVE_VIRTUAL_IP}
- PIHOLE_LB_UPSTREAM_LIST: http://primary.dns.internal:9999 http://secondary.dns.internal:9999
+ PIHOLE_LB_UPSTREAM_LIST: http://primary.dns.internal:1080 http://secondary.dns.internal:1080
# Only on primary
- orbital-sync:
- image: mattwebbio/orbital-sync:1
+ nebula-sync:
+ image: ghcr.io/lovelaze/nebula-sync:latest
network_mode: 'service:pihole'
mem_limit: 50M
depends_on:
@@ -115,27 +114,31 @@ services:
condition: service_started
cpu_count: 1
environment:
- PRIMARY_HOST_BASE_URL: 'http://primary.dns.internal:9999'
- PRIMARY_HOST_PASSWORD: ''
- PRIMARY_HOST_PATH: '/'
- SECONDARY_HOST_1_BASE_URL: 'http://secondary.dns.internal:9999'
- SECONDARY_HOST_1_PASSWORD: ''
- SECONDARY_HOST_1_PATH: '/'
- INTERVAL_MINUTES: 30
+ - PRIMARY=http://primary.dns.internal:1080|
+ - REPLICAS=http://secondary.dns.internal:1080|
+ - FULL_SYNC=false
+ - RUN_GRAVITY=true # Important, rebuilds gravity database after sync
+ - CRON=* * * * * # Or, run every hour: 0 * * * *
+ - CLIENT_SKIP_TLS_VERIFICATION=true
- # See https://github.com/mattwebbio/orbital-sync/blob/master/src/config/schema.ts
- SYNC_WHITELIST: true # Copies the whitelist
- SYNC_REGEX_WHITELIST: true # Copies the regex whitelist
- SYNC_BLACKLIST: true # Copies the blacklist
- SYNC_REGEXLIST: true # Copies the regex blacklist
- SYNC_ADLIST: true # Copies adlists
- SYNC_CLIENT: false # Copies clients
- SYNC_GROUP: true # Copies groups
- SYNC_AUDITLOG: true # Copies the audit log
- SYNC_STATICDHCPLEASES: true # Copies static DHCP leases
- SYNC_LOCALDNSRECORDS: false # Copies local DNS records
- SYNC_LOCALCNAMERECORDS: false # Copies local CNAME records
- SYNC_FLUSHTABLES: true # Clears existing data on the secondary (copy target) Pi-hole
+ # Config synchronisation
+ - SYNC_CONFIG_DNS=false # Keep false - Config items are set by ENV vars and cannot be changed. Produces a 400 from the far-side API if not set. DNS settings are host-specific
+ - SYNC_CONFIG_DHCP=false # Keep false - DHCP should only run on primary
+ - SYNC_CONFIG_NTP=true # Sync NTP settings
+ - SYNC_CONFIG_RESOLVER=true # Sync resolver settings for consistency
+ - SYNC_CONFIG_DATABASE=true # Keep false - Config items are set by ENV vars and cannot be changed
+ - SYNC_CONFIG_MISC=true # Sync miscellaneous settings like nice levels
+ - SYNC_CONFIG_DEBUG=false # Keep debug settings host-specific
+
+ # Gravity/blocking synchronisation
+ - SYNC_GRAVITY_GROUP=true # Sync groups for organisation
+ - SYNC_GRAVITY_AD_LIST=true # Sync blocklists/allowlists
+ - SYNC_GRAVITY_AD_LIST_BY_GROUP=true # Sync which lists apply to which groups
+ - SYNC_GRAVITY_DOMAIN_LIST=true # Sync individual blocked/allowed domains
+ - SYNC_GRAVITY_DOMAIN_LIST_BY_GROUP=true # Sync domain list group assignments
+ - SYNC_GRAVITY_CLIENT=true # Sync client definitions
+ - SYNC_GRAVITY_CLIENT_BY_GROUP=true # Sync client group assignments
+ - SYNC_GRAVITY_DHCP_LEASES=false # Don't sync DHCP leases between hosts
volumes:
enclave-config:
diff --git a/template/docker-compose.secondary.yml b/template/docker-compose.secondary.yml
index ddfe407..fb63f69 100644
--- a/template/docker-compose.secondary.yml
+++ b/template/docker-compose.secondary.yml
@@ -41,7 +41,9 @@ services:
- ./etc/pihole:/etc/pihole
- etc-dnsmasq:/etc/dnsmasq.d
hostname: ${PIHOLE_HOSTNAME}
- mem_limit: 150M
+ # mem_limit: 300M
+ cap_add:
+ - CAP_SYS_TIME
restart: unless-stopped
ports:
- "${ENCLAVE_LOCAL_PORT}:${ENCLAVE_LOCAL_PORT}/tcp"
@@ -54,19 +56,18 @@ services:
gw-net:
environment:
TZ: 'Europe/London'
- WEBPASSWORD: ''
- WEB_PORT: 1080
- # Traffic to the pihole admin interface is
- # proxied through caddy (to apply HTTPS and handle redirects).
- # Restrict the web interface to only be available via that proxy.
- WEB_BIND_ADDR: 127.0.0.1
- CORS_HOSTS: dnsfilter.enclave
- DNSMASQ_LISTENING: all
- FTLCONF_LOCAL_IPV4: ${ENCLAVE_VIRTUAL_IP}
- FTLCONF_BLOCK_IPV4: ${ENCLAVE_VIRTUAL_IP}
- FTLCONF_BLOCKINGMODE: IP-NODATA-AAAA
- FTLCONF_PIHOLE_PTR: NONE
- FTLCONF_MAXDBDAYS: 30
+ FTLCONF_webserver_api_password: ''
+ FTLCONF_webserver_port: 1080
+ # Traffic to the pi-hole admin interface is proxied through Caddy to apply HTTPS and handle redirects,
+ # so we restrict the pi-hole admin interface to only be available via the Caddy proxy.
+ FTLCONF_dns_interface: '127.0.0.1'
+ FTLCONF_dns_domain: 'dnsfilter.enclave'
+ FTLCONF_dns_piholePTR: NONE
+ FTLCONF_dns_listeningMode: all
+ FTLCONF_dns_blocking_mode: IP_NODATA_AAAA
+ FTLCONF_dns_reply_host_IPv4: ${ENCLAVE_VIRTUAL_IP}
+ FTLCONF_dns_reply_blocking_IPv4: ${ENCLAVE_VIRTUAL_IP}
+ FTLCONF_database_maxDBdays: 30
pihole-enclave-sync:
image: enclavenetworks/pihole-enclave-sync:latest
@@ -101,7 +102,7 @@ services:
cpu_count: 1
environment:
PIHOLE_PROXY_BIND_ADDR: ${ENCLAVE_VIRTUAL_IP}
- PIHOLE_LB_UPSTREAM_LIST: http://primary.dns.internal:9999 http://secondary.dns.internal:9999
+ PIHOLE_LB_UPSTREAM_LIST: http://primary.dns.internal:1080 http://secondary.dns.internal:1080
volumes:
enclave-config: