Compare commits
434 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17779bad94 | ||
|
|
fed58f03bf | ||
|
|
c5b3b8dd68 | ||
|
|
46986714d4 | ||
|
|
4f3debcb5b | ||
|
|
223ef72250 | ||
|
|
cf467db61d | ||
|
|
fae1d13892 | ||
|
|
4265bcb178 | ||
|
|
997a771dc8 | ||
|
|
77f0012f6b | ||
|
|
b7b5ffa8dd | ||
|
|
34b66002e9 | ||
|
|
71b560667b | ||
|
|
9dd51b79b5 | ||
|
|
7fd062c4d8 | ||
|
|
3731b65bd5 | ||
|
|
6057b134ae | ||
|
|
0749de3d1f | ||
|
|
d48c557134 | ||
|
|
a705fbca73 | ||
|
|
276c480f50 | ||
|
|
25ba68104b | ||
|
|
3d01e4d0cf | ||
|
|
1b0b0ca445 | ||
|
|
e1a2591c4d | ||
|
|
f8a12917e2 | ||
|
|
37b45d411d | ||
|
|
22ebf21487 | ||
|
|
bf5fffaca7 | ||
|
|
9debd22179 | ||
|
|
a8ce1354c8 | ||
|
|
0a780a959a | ||
|
|
951b4ed002 | ||
|
|
755ec8bf2f | ||
|
|
1c1407e083 | ||
|
|
9463c3c69f | ||
|
|
54bcf5626f | ||
|
|
ba8a50c829 | ||
|
|
bb57a9e616 | ||
|
|
4f4dfe3ac0 | ||
|
|
d4ce5b1c2a | ||
|
|
b6d1bd7335 | ||
|
|
17ec88d96f | ||
|
|
0df38cd64e | ||
|
|
0932c5c498 | ||
|
|
73ca4ebdbc | ||
|
|
da6596e516 | ||
|
|
d88629e23f | ||
|
|
d581401f4e | ||
|
|
60c35cb93c | ||
|
|
2c3fea321b | ||
|
|
40f00c6f0b | ||
|
|
00e51f32b5 | ||
|
|
f90fb8b946 | ||
|
|
2ff1fa1b85 | ||
|
|
7eff36b3bb | ||
|
|
5332b31b92 | ||
|
|
16640ee174 | ||
|
|
5fe170666a | ||
|
|
7e6f81f814 | ||
|
|
80c770357c | ||
|
|
5cc317de5b | ||
|
|
515e5f8c8a | ||
|
|
3d53bda121 | ||
|
|
8bc5b16527 | ||
|
|
c1a927fff1 | ||
|
|
760325eb76 | ||
|
|
bf256aa5a7 | ||
|
|
8dbe6fc0b7 | ||
|
|
fe8b0e98ab | ||
|
|
ef45578af3 | ||
|
|
89b88416b3 | ||
|
|
5d913ad192 | ||
|
|
711035fd8f | ||
|
|
0f74165c9d | ||
|
|
46e1a87e9e | ||
|
|
f998eee467 | ||
|
|
230d6a435f | ||
|
|
53c0982c8b | ||
|
|
d6cfa57ef3 | ||
|
|
49b9dc8888 | ||
|
|
1335c44deb | ||
|
|
9b5ea13a33 | ||
|
|
66eeee5548 | ||
|
|
597c045f9e | ||
|
|
a4b899c256 | ||
|
|
5421aad03e | ||
|
|
eeccfb27f8 | ||
|
|
4cf3280500 | ||
|
|
8c4a9aa6e3 | ||
|
|
9ab566884d | ||
|
|
37102e5a01 | ||
|
|
5a98fa1f76 | ||
|
|
114f562758 | ||
|
|
b3c8045b52 | ||
|
|
a0419bc1f0 | ||
|
|
e35a9da921 | ||
|
|
97447b2f3b | ||
|
|
c67f313ee8 | ||
|
|
49a9f6f2db | ||
|
|
e6683803ed | ||
|
|
27fa284eda | ||
|
|
b98e331375 | ||
|
|
6c9bd7a632 | ||
|
|
5816f495f4 | ||
|
|
5d5a85b7b6 | ||
|
|
c78cf82fc6 | ||
|
|
d77677312c | ||
|
|
d38fcb0549 | ||
|
|
c7410b0be9 | ||
|
|
20c561c83c | ||
|
|
7320c10dd3 | ||
|
|
f418481b9f | ||
|
|
a3516474e8 | ||
|
|
9e2e0019fb | ||
|
|
aef3d89814 | ||
|
|
f2641fb0e5 | ||
|
|
e50438dc11 | ||
|
|
6062df0923 | ||
|
|
989c52ef24 | ||
|
|
4a589286b7 | ||
|
|
3327df8d9c | ||
|
|
3cdaad060b | ||
|
|
0b81dd387b | ||
|
|
64dc002c3f | ||
|
|
6c7a28a7b5 | ||
|
|
21158cb6bc | ||
|
|
71bc237639 | ||
|
|
c6da627b7d | ||
|
|
a3ac1caac6 | ||
|
|
8f3e6f1a50 | ||
|
|
99b7f996e2 | ||
|
|
aa0a9e2976 | ||
|
|
9028898ba7 | ||
|
|
0e8c1ec023 | ||
|
|
313c0ddf28 | ||
|
|
2c38de26b7 | ||
|
|
fc2a564cc0 | ||
|
|
b613758419 | ||
|
|
9c03915cb0 | ||
|
|
e29aa4e205 | ||
|
|
a45c9f9f50 | ||
|
|
b3ba17bfd4 | ||
|
|
2610739624 | ||
|
|
567a915336 | ||
|
|
68eddd2377 | ||
|
|
aeb92416c8 | ||
|
|
cca5c49eaa | ||
|
|
8c778c14dc | ||
|
|
d5c798d1a9 | ||
|
|
14e1eea22d | ||
|
|
ab6b37bdcf | ||
|
|
c8c4eb59b7 | ||
|
|
2651abbe6c | ||
|
|
7b77d991df | ||
|
|
64465510de | ||
|
|
f59749b1c3 | ||
|
|
27ef7e5538 | ||
|
|
a7a467a167 | ||
|
|
21af75a2d2 | ||
|
|
2bd3366bb1 | ||
|
|
d89720330f | ||
|
|
8d1f286f30 | ||
|
|
c7108a632c | ||
|
|
b025cfeea9 | ||
|
|
bc8fcc744c | ||
|
|
a3f1317add | ||
|
|
64d75c012e | ||
|
|
cbcd12631d | ||
|
|
c4f9a475f3 | ||
|
|
71d310c50f | ||
|
|
b486786041 | ||
|
|
3dd26b500d | ||
|
|
aefbe1f5b6 | ||
|
|
13135498c1 | ||
|
|
9f918972d2 | ||
|
|
b25805348f | ||
|
|
d6c48f80f4 | ||
|
|
59dab6a568 | ||
|
|
ecfb96d339 | ||
|
|
e0baf4c7ec | ||
|
|
e4444ae6a5 | ||
|
|
8e4adb6e39 | ||
|
|
6aaa446354 | ||
|
|
7d5f6c8331 | ||
|
|
3d8672bc59 | ||
|
|
b49db58ec2 | ||
|
|
edc808ee89 | ||
|
|
a28d691387 | ||
|
|
56a32047b8 | ||
|
|
ef71ca05a9 | ||
|
|
48d5d6bed2 | ||
|
|
04abc4dacd | ||
|
|
fd41801977 | ||
|
|
1be082a0e1 | ||
|
|
6204698e05 | ||
|
|
edba325a3e | ||
|
|
518cbd10e0 | ||
|
|
0a8761ee68 | ||
|
|
3d4476c9fb | ||
|
|
e05b64b56b | ||
|
|
4150826211 | ||
|
|
469776afd6 | ||
|
|
5c564e53ca | ||
|
|
853cd9670a | ||
|
|
cfbc731eab | ||
|
|
46f991f578 | ||
|
|
ad70ece73e | ||
|
|
39cb1029e9 | ||
|
|
c058a511e6 | ||
|
|
a39c470f2d | ||
|
|
72fcdb128a | ||
|
|
44667b5ffb | ||
|
|
696d1c4ec3 | ||
|
|
0b10c50a0b | ||
|
|
c78aac3051 | ||
|
|
6efb3a3372 | ||
|
|
2845c72bde | ||
|
|
a650641da4 | ||
|
|
1ed5ff306d | ||
|
|
bf57a786e6 | ||
|
|
37889f27de | ||
|
|
80bef5f6b6 | ||
|
|
bd8288d6ef | ||
|
|
98c238064e | ||
|
|
312fa6d134 | ||
|
|
a783da823e | ||
|
|
17485023a2 | ||
|
|
0be987239e | ||
|
|
75f40e7160 | ||
|
|
73d5902bed | ||
|
|
eb045a0dea | ||
|
|
b70b895fc5 | ||
|
|
46331e415c | ||
|
|
dcea3cf2c6 | ||
|
|
e02c7ff249 | ||
|
|
f3d062aaf4 | ||
|
|
bacb98be32 | ||
|
|
7ef7719b6b | ||
|
|
f740e0fefb | ||
|
|
a33f71289d | ||
|
|
8c498acd4c | ||
|
|
3d773beff2 | ||
|
|
d88ab2ca60 | ||
|
|
287d5d37b1 | ||
|
|
f9d1893f96 | ||
|
|
2c5907a8b1 | ||
|
|
954a0c2a14 | ||
|
|
b20aa865b9 | ||
|
|
ed8c6c04d4 | ||
|
|
4b674ecfe3 | ||
|
|
5818f3f997 | ||
|
|
7d731870e5 | ||
|
|
1f26e85399 | ||
|
|
de02220a12 | ||
|
|
4d24fa6c15 | ||
|
|
50d14fb6db | ||
|
|
b6cc845caf | ||
|
|
635b67dbf3 | ||
|
|
e7289563df | ||
|
|
d501b676e9 | ||
|
|
fbc0b57dd1 | ||
|
|
cf0fcf3ad7 | ||
|
|
e2e803f76c | ||
|
|
2c07d27ad7 | ||
|
|
0b9d4a47ad | ||
|
|
67f5f16f84 | ||
|
|
ae9d16baf2 | ||
|
|
fe51a4f8d0 | ||
|
|
300c7b1518 | ||
|
|
5241c1c704 | ||
|
|
dae96e7384 | ||
|
|
3fa8f76d99 | ||
|
|
52c3df1a8e | ||
|
|
477df86ff1 | ||
|
|
b7742ddb9b | ||
|
|
ce8731b746 | ||
|
|
08faf21b2e | ||
|
|
60615e60aa | ||
|
|
2dd08f070e | ||
|
|
110e752552 | ||
|
|
0961103933 | ||
|
|
0fa94e0946 | ||
|
|
9b9acfd4a7 | ||
|
|
82695aba7d | ||
|
|
36dd533ef3 | ||
|
|
2735481da8 | ||
|
|
edec1220fc | ||
|
|
c5b3f6c27a | ||
|
|
1d033ef441 | ||
|
|
83ac2c5005 | ||
|
|
0decc1252b | ||
|
|
f2e1cc9dae | ||
|
|
f7c800863e | ||
|
|
6d73454942 | ||
|
|
2e2a3aa048 | ||
|
|
e23e291dd4 | ||
|
|
6a0c6c4a9b | ||
|
|
94cb0d0a7e | ||
|
|
d78c689e55 | ||
|
|
3915efbfd5 | ||
|
|
853f6b7da2 | ||
|
|
73aa43611f | ||
|
|
c19788dd18 | ||
|
|
71072b4beb | ||
|
|
c9383eab99 | ||
|
|
052a1f294e | ||
|
|
325f20d5c2 | ||
|
|
1c28da7bbd | ||
|
|
aba5e884eb | ||
|
|
9ac5690a7d | ||
|
|
8de814ab34 | ||
|
|
7929a6c133 | ||
|
|
9840148ba9 | ||
|
|
7e223a2a10 | ||
|
|
c9e76c978e | ||
|
|
2601162243 | ||
|
|
37cef84643 | ||
|
|
23e6fa1ec5 | ||
|
|
db116971ce | ||
|
|
2b124b1c69 | ||
|
|
9356d7bbb1 | ||
|
|
29a867d5ae | ||
|
|
86dd612882 | ||
|
|
42d3368955 | ||
|
|
21ae81ffdb | ||
|
|
b33434d02a | ||
|
|
d3e94cbceb | ||
|
|
9b4f6c84cd | ||
|
|
4d31d5ee11 | ||
|
|
9878477896 | ||
|
|
c0a2ab7b77 | ||
|
|
30ba79f6a0 | ||
|
|
cd3c97f113 | ||
|
|
e4a1f3a175 | ||
|
|
6121c162ff | ||
|
|
0d74b27101 | ||
|
|
7fa8cdd03e | ||
|
|
fe9031b26f | ||
|
|
326cd6a1f8 | ||
|
|
063f92f8f4 | ||
|
|
be6a73f102 | ||
|
|
b714c4598a | ||
|
|
0f192998eb | ||
|
|
8a5c7dec71 | ||
|
|
69e4e9a2ae | ||
|
|
4230be0c80 | ||
|
|
d45c9fc522 | ||
|
|
efa99a177e | ||
|
|
c2384ecc6f | ||
|
|
2f38452565 | ||
|
|
5cebceadda | ||
|
|
722a716de3 | ||
|
|
614d18cd3d | ||
|
|
54ce8c2622 | ||
|
|
329c161054 | ||
|
|
f8e84b3c3f | ||
|
|
c9809371ab | ||
|
|
a48750e257 | ||
|
|
0d4c69cc6f | ||
|
|
479b2bc075 | ||
|
|
2ade05d60f | ||
|
|
59fc3804be | ||
|
|
48138d32b6 | ||
|
|
ff5e788889 | ||
|
|
ab7d83384f | ||
|
|
48136c5bbc | ||
|
|
0219e5dfe0 | ||
|
|
0631cb4984 | ||
|
|
40b96e673b | ||
|
|
36ca858668 | ||
|
|
899cac0aac | ||
|
|
16b732fe8a | ||
|
|
1bf2f8d0b7 | ||
|
|
c756bcb9d1 | ||
|
|
42424b515b | ||
|
|
bd956b5f16 | ||
|
|
9be5199f7c | ||
|
|
9db19c5e96 | ||
|
|
91b4233d3a | ||
|
|
0b905c28c1 | ||
|
|
f4286a4d12 | ||
|
|
6ffa2ba1b2 | ||
|
|
e9250d62c5 | ||
|
|
08999bf315 | ||
|
|
2bd670a3dd | ||
|
|
f342b2c9f6 | ||
|
|
2a0bb5b9ee | ||
|
|
c3c5342b48 | ||
|
|
d7d8e9730b | ||
|
|
7c60ee8df1 | ||
|
|
ee9f4856a2 | ||
|
|
444526ad58 | ||
|
|
844c4dcdc8 | ||
|
|
881d92632c | ||
|
|
76d4e1209f | ||
|
|
d956498c8c | ||
|
|
e09dd56807 | ||
|
|
30ec1c94cc | ||
|
|
5d68dac90e | ||
|
|
77e5121d43 | ||
|
|
74d7d10554 | ||
|
|
2f4c4d9176 | ||
|
|
1dd9d55d82 | ||
|
|
8cbffa179d | ||
|
|
5bb79de70b | ||
|
|
534f9a63bf | ||
|
|
f0f5cc52d9 | ||
|
|
bad6d8a59e | ||
|
|
7aa28e4a3a | ||
|
|
e80a7731c9 | ||
|
|
3cd662eaeb | ||
|
|
6ead24b315 | ||
|
|
cdde832ed3 | ||
|
|
57ba60ce54 | ||
|
|
ed6b85241b | ||
|
|
918f7a504c | ||
|
|
3260cb40b5 | ||
|
|
a79c1159a9 | ||
|
|
65a04246cd | ||
|
|
f1245685dc | ||
|
|
ec3a5c2989 | ||
|
|
b20b38d44f | ||
|
|
d5253f26f4 | ||
|
|
a65a841c56 | ||
|
|
1b0b24daf5 | ||
|
|
7010ed454c | ||
|
|
ce86157067 | ||
|
|
3097c8fbdc | ||
|
|
363e2f10bb | ||
|
|
bfd9fe80ef | ||
|
|
c2080324b7 | ||
|
|
5b84cd0a61 |
3
.codespellignore
Normal file
3
.codespellignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
doubleclick
|
||||||
|
wan
|
||||||
|
nwe
|
||||||
@@ -13,26 +13,8 @@ tab_width = 4
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
# Matches multiple files with brace expansion notation
|
[*.yml]
|
||||||
# Set default charset
|
tab_width = 2
|
||||||
[*.{js,py}]
|
|
||||||
charset = utf-8
|
|
||||||
|
|
||||||
# 4 space indentation
|
[*.md]
|
||||||
[*.py]
|
tab_width = 2
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
# Tab indentation (no size specified)
|
|
||||||
[Makefile]
|
|
||||||
indent_style = tab
|
|
||||||
|
|
||||||
# Indentation override for all JS under lib directory
|
|
||||||
[scripts/**.js]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
# Matches the exact files either package.json or .travis.yml
|
|
||||||
[{package.json,.travis.yml}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
|
|||||||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -7,4 +7,6 @@ updates:
|
|||||||
day: saturday
|
day: saturday
|
||||||
time: "10:00"
|
time: "10:00"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
target-branch: developement
|
target-branch: development
|
||||||
|
reviewers:
|
||||||
|
- "pi-hole/core-maintainers"
|
||||||
|
|||||||
7
.github/release.yml
vendored
Normal file
7
.github/release.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
changelog:
|
||||||
|
exclude:
|
||||||
|
labels:
|
||||||
|
- internal
|
||||||
|
authors:
|
||||||
|
- dependabot
|
||||||
|
- github-actions
|
||||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -25,16 +25,16 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout repository
|
name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3.1.0
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
-
|
-
|
||||||
name: Initialize CodeQL
|
name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: 'python'
|
languages: 'python'
|
||||||
-
|
-
|
||||||
name: Autobuild
|
name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@v2
|
||||||
-
|
-
|
||||||
name: Perform CodeQL Analysis
|
name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|||||||
24
.github/workflows/stale.yml
vendored
24
.github/workflows/stale.yml
vendored
@@ -2,7 +2,8 @@ name: Mark stale issues
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '30 * * * *'
|
- cron: '0 8 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
@@ -12,13 +13,14 @@ jobs:
|
|||||||
issues: write
|
issues: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v4
|
- uses: actions/stale@v6.0.1
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
debug-only: true
|
days-before-stale: 30
|
||||||
days-before-stale: 30
|
days-before-close: 5
|
||||||
days-before-close: 5
|
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.'
|
||||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.'
|
stale-issue-label: 'stale'
|
||||||
stale-issue-label: 'Submitter Attention Required'
|
exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed'
|
||||||
exempt-issue-labels: 'pinned, Fixed in next release, Bug: Confirmed'
|
exempt-all-issue-assignees: true
|
||||||
exempt-all-issue-assignees: true
|
operations-per-run: 300
|
||||||
|
close-issue-reason: 'not_planned'
|
||||||
|
|||||||
27
.github/workflows/sync-back-to-dev.yml
vendored
Normal file
27
.github/workflows/sync-back-to-dev.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Sync Back to Development
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync-branches:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Syncing branches
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3.1.0
|
||||||
|
- name: Opening pull request
|
||||||
|
id: pull
|
||||||
|
uses: tretuna/sync-branches@1.4.0
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
FROM_BRANCH: 'master'
|
||||||
|
TO_BRANCH: 'development'
|
||||||
|
- name: Label the pull request to ignore for release note generation
|
||||||
|
uses: actions-ecosystem/action-add-labels@v1.1.3
|
||||||
|
with:
|
||||||
|
labels: internal
|
||||||
|
repo: ${{ github.repository }}
|
||||||
|
number: ${{ steps.pull.outputs.PULL_REQUEST_NUMBER }}
|
||||||
85
.github/workflows/test.yml
vendored
85
.github/workflows/test.yml
vendored
@@ -4,45 +4,72 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened, ready_for_review]
|
types: [opened, synchronize, reopened, ready_for_review]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
smoke-test:
|
smoke-tests:
|
||||||
if: github.event.pull_request.draft == false
|
if: github.event.pull_request.draft == false
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout repository
|
||||||
name: Checkout repository
|
uses: actions/checkout@v3.1.0
|
||||||
uses: actions/checkout@v2
|
|
||||||
-
|
- name: Check scripts in repository are executable
|
||||||
name: Run Smoke Tests
|
run: |
|
||||||
run: |
|
IFS=$'\n';
|
||||||
# Ensure scripts in repository are executable
|
for f in $(find . -name '*.sh'); do if [[ ! -x $f ]]; then echo "$f is not executable" && FAIL=1; fi ;done
|
||||||
IFS=$'\n';
|
unset IFS;
|
||||||
for f in $(find . -name '*.sh'); do if [[ ! -x $f ]]; then echo "$f is not executable" && FAIL=1; fi ;done
|
# If FAIL is 1 then we fail.
|
||||||
unset IFS;
|
[[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!"
|
||||||
# If FAIL is 1 then we fail.
|
|
||||||
[[ $FAIL == 1 ]] && exit 1 || echo "Smoke Tests Passed"
|
- name: Spell-Checking
|
||||||
|
uses: codespell-project/actions-codespell@master
|
||||||
|
with:
|
||||||
|
ignore_words_file: .codespellignore
|
||||||
|
|
||||||
|
- name: Get editorconfig-checker
|
||||||
|
uses: editorconfig-checker/action-editorconfig-checker@main # tag v1.0.0 is really out of date
|
||||||
|
|
||||||
|
- name: Run editorconfig-checker
|
||||||
|
run: editorconfig-checker
|
||||||
|
|
||||||
|
- name: Check python code formatting with black
|
||||||
|
uses: psf/black@stable
|
||||||
|
with:
|
||||||
|
src: "./test"
|
||||||
|
options: "--check --diff --color"
|
||||||
|
|
||||||
distro-test:
|
distro-test:
|
||||||
if: github.event.pull_request.draft == false
|
if: github.event.pull_request.draft == false
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: smoke-test
|
needs: smoke-tests
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
distro: [debian_9, debian_10, debian_11, ubuntu_16, ubuntu_18, ubuntu_20, ubuntu_21, centos_7, centos_8, fedora_33, fedora_34]
|
distro:
|
||||||
|
[
|
||||||
|
debian_10,
|
||||||
|
debian_11,
|
||||||
|
ubuntu_20,
|
||||||
|
ubuntu_22,
|
||||||
|
centos_8,
|
||||||
|
fedora_35,
|
||||||
|
fedora_36,
|
||||||
|
]
|
||||||
env:
|
env:
|
||||||
DISTRO: ${{matrix.distro}}
|
DISTRO: ${{matrix.distro}}
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout repository
|
||||||
name: Checkout repository
|
uses: actions/checkout@v3.1.0
|
||||||
uses: actions/checkout@v2
|
|
||||||
-
|
- name: Set up Python 3.10
|
||||||
name: Set up Python 3.8
|
uses: actions/setup-python@v4.2.0
|
||||||
uses: actions/setup-python@v2
|
with:
|
||||||
with:
|
python-version: "3.10"
|
||||||
python-version: 3.8
|
|
||||||
-
|
- name: Install dependencies
|
||||||
name: Install dependencies
|
run: pip install -r test/requirements.txt
|
||||||
run: pip install -r test/requirements.txt
|
|
||||||
-
|
- name: Test with tox
|
||||||
name: Test with tox
|
run: tox -c test/tox.${DISTRO}.ini
|
||||||
run: tox -c test/tox.${DISTRO}.ini
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
---
|
||||||
linters:
|
linters:
|
||||||
shellcheck:
|
shellcheck:
|
||||||
shell: bash
|
shell: bash
|
||||||
phpcs:
|
phpcs:
|
||||||
flake8:
|
flake8:
|
||||||
max-line-length: 120
|
max-line-length: 120
|
||||||
|
yamllint:
|
||||||
|
config: ./.yamllint.conf
|
||||||
|
remarklint:
|
||||||
|
|||||||
3
.yamllint.conf
Normal file
3
.yamllint.conf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
rules:
|
||||||
|
line-length: disable
|
||||||
|
document-start: disable
|
||||||
@@ -3,5 +3,3 @@
|
|||||||
Please read and understand the contribution guide before creating an issue or pull request.
|
Please read and understand the contribution guide before creating an issue or pull request.
|
||||||
|
|
||||||
The guide can be found here: [https://docs.pi-hole.net/guides/github/contributing/](https://docs.pi-hole.net/guides/github/contributing/)
|
The guide can be found here: [https://docs.pi-hole.net/guides/github/contributing/](https://docs.pi-hole.net/guides/github/contributing/)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -3,12 +3,15 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://pi-hole.net/">
|
<picture>
|
||||||
<img src="https://pi-hole.github.io/graphics/Vortex/Vortex_with_Wordmark.svg" width="150" height="260" alt="Pi-hole">
|
<source media="(prefers-color-scheme: dark)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_darkmode.png">
|
||||||
</a>
|
<source media="(prefers-color-scheme: light)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png">
|
||||||
|
<img src="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png" width="168" height="270" alt="Pi-hole website">
|
||||||
|
</picture>
|
||||||
<br>
|
<br>
|
||||||
<strong>Network-wide ad blocking via your own Linux hardware</strong>
|
<strong>Network-wide ad blocking via your own Linux hardware</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- markdownlint-enable MD033 -->
|
<!-- markdownlint-enable MD033 -->
|
||||||
|
|
||||||
The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content without installing any client-side software.
|
The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content without installing any client-side software.
|
||||||
@@ -19,7 +22,7 @@ The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) th
|
|||||||
- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://docs.pi-hole.net/main/prerequisites/)
|
- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://docs.pi-hole.net/main/prerequisites/)
|
||||||
- **Robust**: a command line interface that is quality assured for interoperability
|
- **Robust**: a command line interface that is quality assured for interoperability
|
||||||
- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole
|
- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole
|
||||||
- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring *all* your devices are protected automatically
|
- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring _all_ your devices are protected automatically
|
||||||
- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware
|
- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware
|
||||||
- **Modern**: blocks ads over both IPv4 and IPv6
|
- **Modern**: blocks ads over both IPv4 and IPv6
|
||||||
- **Free**: open source software that helps ensure _you_ are the sole person in control of your privacy
|
- **Free**: open source software that helps ensure _you_ are the sole person in control of your privacy
|
||||||
@@ -50,7 +53,9 @@ sudo bash basic-install.sh
|
|||||||
wget -O basic-install.sh https://install.pi-hole.net
|
wget -O basic-install.sh https://install.pi-hole.net
|
||||||
sudo bash basic-install.sh
|
sudo bash basic-install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Method 3: Using Docker to deploy Pi-hole
|
### Method 3: Using Docker to deploy Pi-hole
|
||||||
|
|
||||||
Please refer to the [Pi-hole docker repo](https://github.com/pi-hole/docker-pi-hole) to use the Official Docker Images.
|
Please refer to the [Pi-hole docker repo](https://github.com/pi-hole/docker-pi-hole) to use the Official Docker Images.
|
||||||
|
|
||||||
## [Post-install: Make your network take advantage of Pi-hole](https://docs.pi-hole.net/main/post-install/)
|
## [Post-install: Make your network take advantage of Pi-hole](https://docs.pi-hole.net/main/post-install/)
|
||||||
@@ -82,7 +87,7 @@ If you'd rather not donate (_which is okay!_), there are other ways you can help
|
|||||||
- [Hetzner Cloud](https://hetzner.cloud/?ref=7aceisRX3AzA) _affiliate link_
|
- [Hetzner Cloud](https://hetzner.cloud/?ref=7aceisRX3AzA) _affiliate link_
|
||||||
- [Digital Ocean](https://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_
|
- [Digital Ocean](https://www.digitalocean.com/?refcode=344d234950e1) _affiliate link_
|
||||||
- [Stickermule](https://www.stickermule.com/unlock?ref_id=9127301701&utm_medium=link&utm_source=invite) _earn a $10 credit after your first purchase_
|
- [Stickermule](https://www.stickermule.com/unlock?ref_id=9127301701&utm_medium=link&utm_source=invite) _earn a $10 credit after your first purchase_
|
||||||
- [Amazon US](http://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_
|
- [Amazon US](https://www.amazon.com/exec/obidos/redirect-home/pihole09-20) _affiliate link_
|
||||||
- Spreading the word about our software and how you have benefited from it
|
- Spreading the word about our software and how you have benefited from it
|
||||||
|
|
||||||
### Contributing via GitHub
|
### Contributing via GitHub
|
||||||
@@ -112,7 +117,7 @@ While we are primarily reachable on our [Discourse User Forum](https://discourse
|
|||||||
|
|
||||||
### [Faster-than-light Engine](https://github.com/pi-hole/ftl)
|
### [Faster-than-light Engine](https://github.com/pi-hole/ftl)
|
||||||
|
|
||||||
[FTLDNS](https://github.com/pi-hole/ftl) is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTLDNS does this all *very quickly*!
|
[FTLDNS](https://github.com/pi-hole/ftl) is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTLDNS does this all _very quickly_!
|
||||||
|
|
||||||
Some of the statistics you can integrate include:
|
Some of the statistics you can integrate include:
|
||||||
|
|
||||||
@@ -139,7 +144,7 @@ Some notable features include:
|
|||||||
- [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity)
|
- [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity)
|
||||||
- [Querying Ad Lists for blocked domains](https://docs.pi-hole.net/core/pihole-command/#query)
|
- [Querying Ad Lists for blocked domains](https://docs.pi-hole.net/core/pihole-command/#query)
|
||||||
- [Enabling and Disabling Pi-hole](https://docs.pi-hole.net/core/pihole-command/#enable-disable)
|
- [Enabling and Disabling Pi-hole](https://docs.pi-hole.net/core/pihole-command/#enable-disable)
|
||||||
- ... and *many* more!
|
- ... and _many_ more!
|
||||||
|
|
||||||
You can read our [Core Feature Breakdown](https://docs.pi-hole.net/core/pihole-command/#pi-hole-core) for more information.
|
You can read our [Core Feature Breakdown](https://docs.pi-hole.net/core/pihole-command/#pi-hole-core) for more information.
|
||||||
|
|
||||||
@@ -161,4 +166,4 @@ Some notable features include:
|
|||||||
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
|
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
|
||||||
|
|
||||||
1. `http://pi.hole/admin/` (when using Pi-hole as your DNS server)
|
1. `http://pi.hole/admin/` (when using Pi-hole as your DNS server)
|
||||||
2. `http://<IP_ADDPRESS_OF_YOUR_PI_HOLE>/admin/`
|
2. `http://<IP_ADDRESS_OF_YOUR_PI_HOLE>/admin/`
|
||||||
|
|||||||
@@ -29,14 +29,7 @@ bogus-priv
|
|||||||
|
|
||||||
no-resolv
|
no-resolv
|
||||||
|
|
||||||
server=@DNS1@
|
|
||||||
server=@DNS2@
|
|
||||||
|
|
||||||
interface=@INT@
|
|
||||||
|
|
||||||
cache-size=@CACHE_SIZE@
|
|
||||||
|
|
||||||
log-queries
|
log-queries
|
||||||
log-facility=/var/log/pihole.log
|
log-facility=/var/log/pihole/pihole.log
|
||||||
|
|
||||||
log-async
|
log-async
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 B |
Binary file not shown.
|
Before Width: | Height: | Size: 26 B |
Binary file not shown.
|
Before Width: | Height: | Size: 37 B |
Binary file not shown.
|
Before Width: | Height: | Size: 43 B |
@@ -1,5 +1,5 @@
|
|||||||
# Determine if terminal is capable of showing colors
|
# Determine if terminal is capable of showing colors
|
||||||
if [[ -t 1 ]] && [[ $(tput colors) -ge 8 ]]; then
|
if ([[ -t 1 ]] && [[ $(tput colors) -ge 8 ]]) || [[ "${WEBCALL}" ]]; then
|
||||||
# Bold and underline may not show up on all clients
|
# Bold and underline may not show up on all clients
|
||||||
# If something MUST be emphasized, use both
|
# If something MUST be emphasized, use both
|
||||||
COL_BOLD='[1m'
|
COL_BOLD='[1m'
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ LC_NUMERIC=C
|
|||||||
# Retrieve stats from FTL engine
|
# Retrieve stats from FTL engine
|
||||||
pihole-FTL() {
|
pihole-FTL() {
|
||||||
local ftl_port LINE
|
local ftl_port LINE
|
||||||
ftl_port=$(cat /run/pihole-FTL.port 2> /dev/null)
|
# shellcheck disable=SC1091
|
||||||
|
. /opt/pihole/utils.sh
|
||||||
|
ftl_port=$(getFTLAPIPort)
|
||||||
if [[ -n "$ftl_port" ]]; then
|
if [[ -n "$ftl_port" ]]; then
|
||||||
# Open connection to FTL
|
# Open connection to FTL
|
||||||
exec 3<>"/dev/tcp/127.0.0.1/$ftl_port"
|
exec 3<>"/dev/tcp/127.0.0.1/$ftl_port"
|
||||||
@@ -503,11 +505,11 @@ chronoFunc() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
printFunc " Pi-hole: " "$ph_status" "$ph_info"
|
printFunc " Pi-hole: " "$ph_status" "$ph_info"
|
||||||
printFunc " Ads Today: " "$ads_percentage_today%" "$ads_info"
|
printFunc " Blocked: " "$ads_percentage_today%" "$ads_info"
|
||||||
printFunc "Local Qrys: " "$queries_cached_percentage%" "$dns_info"
|
printFunc "Local Qrys: " "$queries_cached_percentage%" "$dns_info"
|
||||||
|
|
||||||
printFunc " Blocked: " "$recent_blocked"
|
printFunc "Last Block: " "$recent_blocked"
|
||||||
printFunc "Top Advert: " "$top_ad"
|
printFunc " Top Block: " "$top_ad"
|
||||||
|
|
||||||
# Provide more stats on screens with more lines
|
# Provide more stats on screens with more lines
|
||||||
if [[ "$scr_lines" -eq 17 ]]; then
|
if [[ "$scr_lines" -eq 17 ]]; then
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ upgrade_gravityDB(){
|
|||||||
auditFile="${piholeDir}/auditlog.list"
|
auditFile="${piholeDir}/auditlog.list"
|
||||||
|
|
||||||
# Get database version
|
# Get database version
|
||||||
version="$(sqlite3 "${database}" "SELECT \"value\" FROM \"info\" WHERE \"property\" = 'version';")"
|
version="$(pihole-FTL sqlite3 "${database}" "SELECT \"value\" FROM \"info\" WHERE \"property\" = 'version';")"
|
||||||
|
|
||||||
if [[ "$version" == "1" ]]; then
|
if [[ "$version" == "1" ]]; then
|
||||||
# This migration script upgrades the gravity.db file by
|
# This migration script upgrades the gravity.db file by
|
||||||
# adding the domain_audit table
|
# adding the domain_audit table
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 1 to 2"
|
echo -e " ${INFO} Upgrading gravity database from version 1 to 2"
|
||||||
sqlite3 "${database}" < "${scriptPath}/1_to_2.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/1_to_2.sql"
|
||||||
version=2
|
version=2
|
||||||
|
|
||||||
# Store audit domains in database table
|
# Store audit domains in database table
|
||||||
@@ -40,28 +40,28 @@ upgrade_gravityDB(){
|
|||||||
# renaming the regex table to regex_blacklist, and
|
# renaming the regex table to regex_blacklist, and
|
||||||
# creating a new regex_whitelist table + corresponding linking table and views
|
# creating a new regex_whitelist table + corresponding linking table and views
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 2 to 3"
|
echo -e " ${INFO} Upgrading gravity database from version 2 to 3"
|
||||||
sqlite3 "${database}" < "${scriptPath}/2_to_3.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/2_to_3.sql"
|
||||||
version=3
|
version=3
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "3" ]]; then
|
if [[ "$version" == "3" ]]; then
|
||||||
# This migration script unifies the formally separated domain
|
# This migration script unifies the formally separated domain
|
||||||
# lists into a single table with a UNIQUE domain constraint
|
# lists into a single table with a UNIQUE domain constraint
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 3 to 4"
|
echo -e " ${INFO} Upgrading gravity database from version 3 to 4"
|
||||||
sqlite3 "${database}" < "${scriptPath}/3_to_4.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/3_to_4.sql"
|
||||||
version=4
|
version=4
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "4" ]]; then
|
if [[ "$version" == "4" ]]; then
|
||||||
# This migration script upgrades the gravity and list views
|
# This migration script upgrades the gravity and list views
|
||||||
# implementing necessary changes for per-client blocking
|
# implementing necessary changes for per-client blocking
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 4 to 5"
|
echo -e " ${INFO} Upgrading gravity database from version 4 to 5"
|
||||||
sqlite3 "${database}" < "${scriptPath}/4_to_5.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/4_to_5.sql"
|
||||||
version=5
|
version=5
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "5" ]]; then
|
if [[ "$version" == "5" ]]; then
|
||||||
# This migration script upgrades the adlist view
|
# This migration script upgrades the adlist view
|
||||||
# to return an ID used in gravity.sh
|
# to return an ID used in gravity.sh
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 5 to 6"
|
echo -e " ${INFO} Upgrading gravity database from version 5 to 6"
|
||||||
sqlite3 "${database}" < "${scriptPath}/5_to_6.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/5_to_6.sql"
|
||||||
version=6
|
version=6
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "6" ]]; then
|
if [[ "$version" == "6" ]]; then
|
||||||
@@ -69,7 +69,7 @@ upgrade_gravityDB(){
|
|||||||
# which is automatically associated to all clients not
|
# which is automatically associated to all clients not
|
||||||
# having their own group assignments
|
# having their own group assignments
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 6 to 7"
|
echo -e " ${INFO} Upgrading gravity database from version 6 to 7"
|
||||||
sqlite3 "${database}" < "${scriptPath}/6_to_7.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/6_to_7.sql"
|
||||||
version=7
|
version=7
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "7" ]]; then
|
if [[ "$version" == "7" ]]; then
|
||||||
@@ -77,21 +77,21 @@ upgrade_gravityDB(){
|
|||||||
# to ensure uniqueness on the group name
|
# to ensure uniqueness on the group name
|
||||||
# We also add date_added and date_modified columns
|
# We also add date_added and date_modified columns
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 7 to 8"
|
echo -e " ${INFO} Upgrading gravity database from version 7 to 8"
|
||||||
sqlite3 "${database}" < "${scriptPath}/7_to_8.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/7_to_8.sql"
|
||||||
version=8
|
version=8
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "8" ]]; then
|
if [[ "$version" == "8" ]]; then
|
||||||
# This migration fixes some issues that were introduced
|
# This migration fixes some issues that were introduced
|
||||||
# in the previous migration script.
|
# in the previous migration script.
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 8 to 9"
|
echo -e " ${INFO} Upgrading gravity database from version 8 to 9"
|
||||||
sqlite3 "${database}" < "${scriptPath}/8_to_9.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/8_to_9.sql"
|
||||||
version=9
|
version=9
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "9" ]]; then
|
if [[ "$version" == "9" ]]; then
|
||||||
# This migration drops unused tables and creates triggers to remove
|
# This migration drops unused tables and creates triggers to remove
|
||||||
# obsolete groups assignments when the linked items are deleted
|
# obsolete groups assignments when the linked items are deleted
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 9 to 10"
|
echo -e " ${INFO} Upgrading gravity database from version 9 to 10"
|
||||||
sqlite3 "${database}" < "${scriptPath}/9_to_10.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/9_to_10.sql"
|
||||||
version=10
|
version=10
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "10" ]]; then
|
if [[ "$version" == "10" ]]; then
|
||||||
@@ -101,31 +101,31 @@ upgrade_gravityDB(){
|
|||||||
# to keep the copying process generic (needs the same columns in both the
|
# to keep the copying process generic (needs the same columns in both the
|
||||||
# source and the destination databases).
|
# source and the destination databases).
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 10 to 11"
|
echo -e " ${INFO} Upgrading gravity database from version 10 to 11"
|
||||||
sqlite3 "${database}" < "${scriptPath}/10_to_11.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/10_to_11.sql"
|
||||||
version=11
|
version=11
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "11" ]]; then
|
if [[ "$version" == "11" ]]; then
|
||||||
# Rename group 0 from "Unassociated" to "Default"
|
# Rename group 0 from "Unassociated" to "Default"
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 11 to 12"
|
echo -e " ${INFO} Upgrading gravity database from version 11 to 12"
|
||||||
sqlite3 "${database}" < "${scriptPath}/11_to_12.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/11_to_12.sql"
|
||||||
version=12
|
version=12
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "12" ]]; then
|
if [[ "$version" == "12" ]]; then
|
||||||
# Add column date_updated to adlist table
|
# Add column date_updated to adlist table
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 12 to 13"
|
echo -e " ${INFO} Upgrading gravity database from version 12 to 13"
|
||||||
sqlite3 "${database}" < "${scriptPath}/12_to_13.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/12_to_13.sql"
|
||||||
version=13
|
version=13
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "13" ]]; then
|
if [[ "$version" == "13" ]]; then
|
||||||
# Add columns number and status to adlist table
|
# Add columns number and status to adlist table
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 13 to 14"
|
echo -e " ${INFO} Upgrading gravity database from version 13 to 14"
|
||||||
sqlite3 "${database}" < "${scriptPath}/13_to_14.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/13_to_14.sql"
|
||||||
version=14
|
version=14
|
||||||
fi
|
fi
|
||||||
if [[ "$version" == "14" ]]; then
|
if [[ "$version" == "14" ]]; then
|
||||||
# Changes the vw_adlist created in 5_to_6
|
# Changes the vw_adlist created in 5_to_6
|
||||||
echo -e " ${INFO} Upgrading gravity database from version 14 to 15"
|
echo -e " ${INFO} Upgrading gravity database from version 14 to 15"
|
||||||
sqlite3 "${database}" < "${scriptPath}/14_to_15.sql"
|
pihole-FTL sqlite3 "${database}" < "${scriptPath}/14_to_15.sql"
|
||||||
version=15
|
version=15
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ CREATE TRIGGER tr_group_zero AFTER DELETE ON "group"
|
|||||||
|
|
||||||
UPDATE info SET value = 12 WHERE property = 'version';
|
UPDATE info SET value = 12 WHERE property = 'version';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -15,4 +15,4 @@ CREATE TRIGGER tr_adlist_update AFTER UPDATE OF address,enabled,comment ON adlis
|
|||||||
|
|
||||||
UPDATE info SET value = 13 WHERE property = 'version';
|
UPDATE info SET value = 13 WHERE property = 'version';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -93,4 +93,4 @@ CREATE VIEW vw_regex_blacklist AS SELECT domain, domainlist.id AS id, domainlist
|
|||||||
|
|
||||||
UPDATE info SET value = 4 WHERE property = 'version';
|
UPDATE info SET value = 4 WHERE property = 'version';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ CREATE TABLE client_by_group
|
|||||||
|
|
||||||
UPDATE info SET value = 5 WHERE property = 'version';
|
UPDATE info SET value = 5 WHERE property = 'version';
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -100,21 +100,29 @@ Options:
|
|||||||
ValidateDomain() {
|
ValidateDomain() {
|
||||||
# Convert to lowercase
|
# Convert to lowercase
|
||||||
domain="${1,,}"
|
domain="${1,,}"
|
||||||
|
local str validDomain
|
||||||
|
|
||||||
# Check validity of domain (don't check for regex entries)
|
# Check validity of domain (don't check for regex entries)
|
||||||
if [[ "${#domain}" -le 253 ]]; then
|
if [[ ( "${typeId}" == "${regex_blacklist}" || "${typeId}" == "${regex_whitelist}" ) && "${wildcard}" == false ]]; then
|
||||||
if [[ ( "${typeId}" == "${regex_blacklist}" || "${typeId}" == "${regex_whitelist}" ) && "${wildcard}" == false ]]; then
|
validDomain="${domain}"
|
||||||
validDomain="${domain}"
|
else
|
||||||
else
|
# Check max length
|
||||||
|
if [[ "${#domain}" -le 253 ]]; then
|
||||||
validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check
|
validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check
|
||||||
validDomain=$(grep -P "^[^\\.]{1,63}(\\.[^\\.]{1,63})*$" <<< "${validDomain}") # Length of each label
|
validDomain=$(grep -P "^[^\\.]{1,63}(\\.[^\\.]{1,63})*$" <<< "${validDomain}") # Length of each label
|
||||||
|
# set error string
|
||||||
|
str="is not a valid argument or domain name!"
|
||||||
|
else
|
||||||
|
validDomain=
|
||||||
|
str="is too long!"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${validDomain}" ]]; then
|
if [[ -n "${validDomain}" ]]; then
|
||||||
domList=("${domList[@]}" "${validDomain}")
|
domList=("${domList[@]}" "${validDomain}")
|
||||||
else
|
else
|
||||||
echo -e " ${CROSS} ${domain} is not a valid argument or domain name!"
|
echo -e " ${CROSS} ${domain} ${str}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
domaincount=$((domaincount+1))
|
domaincount=$((domaincount+1))
|
||||||
@@ -142,18 +150,18 @@ AddDomain() {
|
|||||||
domain="$1"
|
domain="$1"
|
||||||
|
|
||||||
# Is the domain in the list we want to add it to?
|
# Is the domain in the list we want to add it to?
|
||||||
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM domainlist WHERE domain = '${domain}';")"
|
num="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM domainlist WHERE domain = '${domain}';")"
|
||||||
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
||||||
|
|
||||||
if [[ "${num}" -ne 0 ]]; then
|
if [[ "${num}" -ne 0 ]]; then
|
||||||
existingTypeId="$(sqlite3 "${gravityDBfile}" "SELECT type FROM domainlist WHERE domain = '${domain}';")"
|
existingTypeId="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT type FROM domainlist WHERE domain = '${domain}';")"
|
||||||
if [[ "${existingTypeId}" == "${typeId}" ]]; then
|
if [[ "${existingTypeId}" == "${typeId}" ]]; then
|
||||||
if [[ "${verbose}" == true ]]; then
|
if [[ "${verbose}" == true ]]; then
|
||||||
echo -e " ${INFO} ${1} already exists in ${requestedListname}, no need to add!"
|
echo -e " ${INFO} ${1} already exists in ${requestedListname}, no need to add!"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
existingListname="$(GetListnameFromTypeId "${existingTypeId}")"
|
existingListname="$(GetListnameFromTypeId "${existingTypeId}")"
|
||||||
sqlite3 "${gravityDBfile}" "UPDATE domainlist SET type = ${typeId} WHERE domain='${domain}';"
|
pihole-FTL sqlite3 "${gravityDBfile}" "UPDATE domainlist SET type = ${typeId} WHERE domain='${domain}';"
|
||||||
if [[ "${verbose}" == true ]]; then
|
if [[ "${verbose}" == true ]]; then
|
||||||
echo -e " ${INFO} ${1} already exists in ${existingListname}, it has been moved to ${requestedListname}!"
|
echo -e " ${INFO} ${1} already exists in ${existingListname}, it has been moved to ${requestedListname}!"
|
||||||
fi
|
fi
|
||||||
@@ -169,10 +177,10 @@ AddDomain() {
|
|||||||
# Insert only the domain here. The enabled and date_added fields will be filled
|
# Insert only the domain here. The enabled and date_added fields will be filled
|
||||||
# with their default values (enabled = true, date_added = current timestamp)
|
# with their default values (enabled = true, date_added = current timestamp)
|
||||||
if [[ -z "${comment}" ]]; then
|
if [[ -z "${comment}" ]]; then
|
||||||
sqlite3 "${gravityDBfile}" "INSERT INTO domainlist (domain,type) VALUES ('${domain}',${typeId});"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT INTO domainlist (domain,type) VALUES ('${domain}',${typeId});"
|
||||||
else
|
else
|
||||||
# also add comment when variable has been set through the "--comment" option
|
# also add comment when variable has been set through the "--comment" option
|
||||||
sqlite3 "${gravityDBfile}" "INSERT INTO domainlist (domain,type,comment) VALUES ('${domain}',${typeId},'${comment}');"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT INTO domainlist (domain,type,comment) VALUES ('${domain}',${typeId},'${comment}');"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +189,7 @@ RemoveDomain() {
|
|||||||
domain="$1"
|
domain="$1"
|
||||||
|
|
||||||
# Is the domain in the list we want to remove it from?
|
# Is the domain in the list we want to remove it from?
|
||||||
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM domainlist WHERE domain = '${domain}' AND type = ${typeId};")"
|
num="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM domainlist WHERE domain = '${domain}' AND type = ${typeId};")"
|
||||||
|
|
||||||
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
||||||
|
|
||||||
@@ -198,14 +206,14 @@ RemoveDomain() {
|
|||||||
fi
|
fi
|
||||||
reload=true
|
reload=true
|
||||||
# Remove it from the current list
|
# Remove it from the current list
|
||||||
sqlite3 "${gravityDBfile}" "DELETE FROM domainlist WHERE domain = '${domain}' AND type = ${typeId};"
|
pihole-FTL sqlite3 "${gravityDBfile}" "DELETE FROM domainlist WHERE domain = '${domain}' AND type = ${typeId};"
|
||||||
}
|
}
|
||||||
|
|
||||||
Displaylist() {
|
Displaylist() {
|
||||||
local count num_pipes domain enabled status nicedate requestedListname
|
local count num_pipes domain enabled status nicedate requestedListname
|
||||||
|
|
||||||
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
requestedListname="$(GetListnameFromTypeId "${typeId}")"
|
||||||
data="$(sqlite3 "${gravityDBfile}" "SELECT domain,enabled,date_modified FROM domainlist WHERE type = ${typeId};" 2> /dev/null)"
|
data="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT domain,enabled,date_modified FROM domainlist WHERE type = ${typeId};" 2> /dev/null)"
|
||||||
|
|
||||||
if [[ -z $data ]]; then
|
if [[ -z $data ]]; then
|
||||||
echo -e "Not showing empty list"
|
echo -e "Not showing empty list"
|
||||||
@@ -243,10 +251,10 @@ Displaylist() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NukeList() {
|
NukeList() {
|
||||||
count=$(sqlite3 "${gravityDBfile}" "SELECT COUNT(1) FROM domainlist WHERE type = ${typeId};")
|
count=$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(1) FROM domainlist WHERE type = ${typeId};")
|
||||||
listname="$(GetListnameFromTypeId "${typeId}")"
|
listname="$(GetListnameFromTypeId "${typeId}")"
|
||||||
if [ "$count" -gt 0 ];then
|
if [ "$count" -gt 0 ];then
|
||||||
sqlite3 "${gravityDBfile}" "DELETE FROM domainlist WHERE type = ${typeId};"
|
pihole-FTL sqlite3 "${gravityDBfile}" "DELETE FROM domainlist WHERE type = ${typeId};"
|
||||||
echo " ${TICK} Removed ${count} domain(s) from the ${listname}"
|
echo " ${TICK} Removed ${count} domain(s) from the ${listname}"
|
||||||
else
|
else
|
||||||
echo " ${INFO} ${listname} already empty. Nothing to do!"
|
echo " ${INFO} ${listname} already empty. Nothing to do!"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ flushARP(){
|
|||||||
# Truncate network_addresses table in pihole-FTL.db
|
# Truncate network_addresses table in pihole-FTL.db
|
||||||
# This needs to be done before we can truncate the network table due to
|
# This needs to be done before we can truncate the network table due to
|
||||||
# foreign key constraints
|
# foreign key constraints
|
||||||
if ! output=$(sqlite3 "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then
|
if ! output=$(pihole-FTL sqlite3 "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then
|
||||||
echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table"
|
echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table"
|
||||||
echo " Database location: ${DBFILE}"
|
echo " Database location: ${DBFILE}"
|
||||||
echo " Output: ${output}"
|
echo " Output: ${output}"
|
||||||
@@ -47,7 +47,7 @@ flushARP(){
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Truncate network table in pihole-FTL.db
|
# Truncate network table in pihole-FTL.db
|
||||||
if ! output=$(sqlite3 "${DBFILE}" "DELETE FROM network" 2>&1); then
|
if ! output=$(pihole-FTL sqlite3 "${DBFILE}" "DELETE FROM network" 2>&1); then
|
||||||
echo -e "${OVER} ${CROSS} Failed to truncate network table"
|
echo -e "${OVER} ${CROSS} Failed to truncate network table"
|
||||||
echo " Database location: ${DBFILE}"
|
echo " Database location: ${DBFILE}"
|
||||||
echo " Output: ${output}"
|
echo " Output: ${output}"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# Please see LICENSE file for your rights under this license.
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
PH_TEST="true"
|
SKIP_INSTALL="true"
|
||||||
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
|
|
||||||
# webInterfaceGitUrl set in basic-install.sh
|
# webInterfaceGitUrl set in basic-install.sh
|
||||||
@@ -42,6 +42,11 @@ warning1() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCheckFunc() {
|
||||||
|
/opt/pihole/updatecheck.sh
|
||||||
|
/opt/pihole/updatecheck.sh x remote
|
||||||
|
}
|
||||||
|
|
||||||
checkout() {
|
checkout() {
|
||||||
local corebranches
|
local corebranches
|
||||||
local webbranches
|
local webbranches
|
||||||
@@ -164,6 +169,8 @@ checkout() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
checkout_pull_branch "${webInterfaceDir}" "${2}"
|
checkout_pull_branch "${webInterfaceDir}" "${2}"
|
||||||
|
# Force an update of the updatechecker
|
||||||
|
updateCheckFunc
|
||||||
elif [[ "${1}" == "ftl" ]] ; then
|
elif [[ "${1}" == "ftl" ]] ; then
|
||||||
local path
|
local path
|
||||||
local oldbranch
|
local oldbranch
|
||||||
@@ -178,6 +185,8 @@ checkout() {
|
|||||||
FTLinstall "${binary}"
|
FTLinstall "${binary}"
|
||||||
restart_service pihole-FTL
|
restart_service pihole-FTL
|
||||||
enable_service pihole-FTL
|
enable_service pihole-FTL
|
||||||
|
# Force an update of the updatechecker
|
||||||
|
updateCheckFunc
|
||||||
else
|
else
|
||||||
echo " ${CROSS} Requested branch \"${2}\" is not available"
|
echo " ${CROSS} Requested branch \"${2}\" is not available"
|
||||||
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') )
|
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep 'heads' | sed 's/refs\/heads\///;s/ //g' | awk '{print $2}') )
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ else
|
|||||||
#OVER="\r\033[K"
|
#OVER="\r\033[K"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /etc/pihole/versions
|
||||||
|
|
||||||
OBFUSCATED_PLACEHOLDER="<DOMAIN OBFUSCATED>"
|
OBFUSCATED_PLACEHOLDER="<DOMAIN OBFUSCATED>"
|
||||||
|
|
||||||
# FAQ URLs for use in showing the debug log
|
# FAQ URLs for use in showing the debug log
|
||||||
@@ -50,7 +53,6 @@ FAQ_HARDWARE_REQUIREMENTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisite
|
|||||||
FAQ_HARDWARE_REQUIREMENTS_PORTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#ports${COL_NC}"
|
FAQ_HARDWARE_REQUIREMENTS_PORTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#ports${COL_NC}"
|
||||||
FAQ_HARDWARE_REQUIREMENTS_FIREWALLD="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#firewalld${COL_NC}"
|
FAQ_HARDWARE_REQUIREMENTS_FIREWALLD="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#firewalld${COL_NC}"
|
||||||
FAQ_GATEWAY="${COL_CYAN}https://discourse.pi-hole.net/t/why-is-a-default-gateway-important-for-pi-hole/3546${COL_NC}"
|
FAQ_GATEWAY="${COL_CYAN}https://discourse.pi-hole.net/t/why-is-a-default-gateway-important-for-pi-hole/3546${COL_NC}"
|
||||||
FAQ_ULA="${COL_CYAN}https://discourse.pi-hole.net/t/use-ipv6-ula-addresses-for-pi-hole/2127${COL_NC}"
|
|
||||||
FAQ_FTL_COMPATIBILITY="${COL_CYAN}https://github.com/pi-hole/FTL#compatibility-list${COL_NC}"
|
FAQ_FTL_COMPATIBILITY="${COL_CYAN}https://github.com/pi-hole/FTL#compatibility-list${COL_NC}"
|
||||||
FAQ_BAD_ADDRESS="${COL_CYAN}https://discourse.pi-hole.net/t/why-do-i-see-bad-address-at-in-pihole-log/3972${COL_NC}"
|
FAQ_BAD_ADDRESS="${COL_CYAN}https://discourse.pi-hole.net/t/why-do-i-see-bad-address-at-in-pihole-log/3972${COL_NC}"
|
||||||
|
|
||||||
@@ -66,8 +68,8 @@ PIHOLE_DIRECTORY="/etc/pihole"
|
|||||||
PIHOLE_SCRIPTS_DIRECTORY="/opt/pihole"
|
PIHOLE_SCRIPTS_DIRECTORY="/opt/pihole"
|
||||||
BIN_DIRECTORY="/usr/local/bin"
|
BIN_DIRECTORY="/usr/local/bin"
|
||||||
RUN_DIRECTORY="/run"
|
RUN_DIRECTORY="/run"
|
||||||
LOG_DIRECTORY="/var/log"
|
LOG_DIRECTORY="/var/log/pihole"
|
||||||
WEB_SERVER_LOG_DIRECTORY="${LOG_DIRECTORY}/lighttpd"
|
WEB_SERVER_LOG_DIRECTORY="/var/log/lighttpd"
|
||||||
WEB_SERVER_CONFIG_DIRECTORY="/etc/lighttpd"
|
WEB_SERVER_CONFIG_DIRECTORY="/etc/lighttpd"
|
||||||
HTML_DIRECTORY="/var/www/html"
|
HTML_DIRECTORY="/var/www/html"
|
||||||
WEB_GIT_DIRECTORY="${HTML_DIRECTORY}/admin"
|
WEB_GIT_DIRECTORY="${HTML_DIRECTORY}/admin"
|
||||||
@@ -124,41 +126,21 @@ PIHOLE_COMMAND="${BIN_DIRECTORY}/pihole"
|
|||||||
PIHOLE_COLTABLE_FILE="${BIN_DIRECTORY}/COL_TABLE"
|
PIHOLE_COLTABLE_FILE="${BIN_DIRECTORY}/COL_TABLE"
|
||||||
|
|
||||||
FTL_PID="${RUN_DIRECTORY}/pihole-FTL.pid"
|
FTL_PID="${RUN_DIRECTORY}/pihole-FTL.pid"
|
||||||
FTL_PORT="${RUN_DIRECTORY}/pihole-FTL.port"
|
|
||||||
|
|
||||||
PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log"
|
PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log"
|
||||||
PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*"
|
PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*"
|
||||||
PIHOLE_DEBUG_LOG="${LOG_DIRECTORY}/pihole_debug.log"
|
PIHOLE_DEBUG_LOG="${LOG_DIRECTORY}/pihole_debug.log"
|
||||||
PIHOLE_FTL_LOG="$(get_ftl_conf_value "LOGFILE" "${LOG_DIRECTORY}/pihole-FTL.log")"
|
PIHOLE_FTL_LOG="$(get_ftl_conf_value "LOGFILE" "${LOG_DIRECTORY}/FTL.log")"
|
||||||
|
|
||||||
PIHOLE_WEB_SERVER_ACCESS_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/access.log"
|
PIHOLE_WEB_SERVER_ACCESS_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/access-pihole.log"
|
||||||
PIHOLE_WEB_SERVER_ERROR_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/error.log"
|
PIHOLE_WEB_SERVER_ERROR_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/error-pihole.log"
|
||||||
|
|
||||||
RESOLVCONF="${ETC}/resolv.conf"
|
RESOLVCONF="${ETC}/resolv.conf"
|
||||||
DNSMASQ_CONF="${ETC}/dnsmasq.conf"
|
DNSMASQ_CONF="${ETC}/dnsmasq.conf"
|
||||||
|
|
||||||
# An array of operating system "pretty names" that we officially support
|
|
||||||
# We can loop through the array at any time to see if it matches a value
|
|
||||||
#SUPPORTED_OS=("Raspbian" "Ubuntu" "Fedora" "Debian" "CentOS")
|
|
||||||
|
|
||||||
# Store Pi-hole's processes in an array for easy use and parsing
|
# Store Pi-hole's processes in an array for easy use and parsing
|
||||||
PIHOLE_PROCESSES=( "lighttpd" "pihole-FTL" )
|
PIHOLE_PROCESSES=( "lighttpd" "pihole-FTL" )
|
||||||
|
|
||||||
# Store the required directories in an array so it can be parsed through
|
|
||||||
#REQUIRED_DIRECTORIES=("${CORE_GIT_DIRECTORY}"
|
|
||||||
#"${CRON_D_DIRECTORY}"
|
|
||||||
#"${DNSMASQ_D_DIRECTORY}"
|
|
||||||
#"${PIHOLE_DIRECTORY}"
|
|
||||||
#"${PIHOLE_SCRIPTS_DIRECTORY}"
|
|
||||||
#"${BIN_DIRECTORY}"
|
|
||||||
#"${RUN_DIRECTORY}"
|
|
||||||
#"${LOG_DIRECTORY}"
|
|
||||||
#"${WEB_SERVER_LOG_DIRECTORY}"
|
|
||||||
#"${WEB_SERVER_CONFIG_DIRECTORY}"
|
|
||||||
#"${HTML_DIRECTORY}"
|
|
||||||
#"${WEB_GIT_DIRECTORY}"
|
|
||||||
#"${BLOCK_PAGE_DIRECTORY}")
|
|
||||||
|
|
||||||
# Store the required directories in an array so it can be parsed through
|
# Store the required directories in an array so it can be parsed through
|
||||||
REQUIRED_FILES=("${PIHOLE_CRON_FILE}"
|
REQUIRED_FILES=("${PIHOLE_CRON_FILE}"
|
||||||
"${WEB_SERVER_CONFIG_FILE}"
|
"${WEB_SERVER_CONFIG_FILE}"
|
||||||
@@ -172,7 +154,6 @@ REQUIRED_FILES=("${PIHOLE_CRON_FILE}"
|
|||||||
"${PIHOLE_COMMAND}"
|
"${PIHOLE_COMMAND}"
|
||||||
"${PIHOLE_COLTABLE_FILE}"
|
"${PIHOLE_COLTABLE_FILE}"
|
||||||
"${FTL_PID}"
|
"${FTL_PID}"
|
||||||
"${FTL_PORT}"
|
|
||||||
"${PIHOLE_LOG}"
|
"${PIHOLE_LOG}"
|
||||||
"${PIHOLE_LOG_GZIPS}"
|
"${PIHOLE_LOG_GZIPS}"
|
||||||
"${PIHOLE_DEBUG_LOG}"
|
"${PIHOLE_DEBUG_LOG}"
|
||||||
@@ -351,17 +332,34 @@ compare_local_version_to_git_version() {
|
|||||||
|
|
||||||
check_ftl_version() {
|
check_ftl_version() {
|
||||||
local ftl_name="FTL"
|
local ftl_name="FTL"
|
||||||
|
local FTL_VERSION FTL_COMMIT FTL_BRANCH
|
||||||
echo_current_diagnostic "${ftl_name} version"
|
echo_current_diagnostic "${ftl_name} version"
|
||||||
# Use the built in command to check FTL's version
|
# Use the built in command to check FTL's version
|
||||||
FTL_VERSION=$(pihole-FTL version)
|
FTL_VERSION=$(pihole-FTL -vv | grep -m 1 Version | awk '{printf $2}')
|
||||||
|
FTL_BRANCH=$(pihole-FTL -vv | grep -m 1 Branch | awk '{printf $2}')
|
||||||
|
FTL_COMMIT=$(pihole-FTL -vv | grep -m 1 Commit | awk '{printf $2}')
|
||||||
|
|
||||||
# Compare the current FTL version to the remote version
|
# Compare the current FTL version to the remote version
|
||||||
if [[ "${FTL_VERSION}" == "$(pihole -v | awk '/FTL/ {print $6}' | cut -d ')' -f1)" ]]; then
|
if [[ "${FTL_VERSION}" == "$(pihole -v | awk '/FTL/ {print $6}' | cut -d ')' -f1)" ]]; then
|
||||||
# If they are the same, FTL is up-to-date
|
# If they are the same, FTL is up-to-date
|
||||||
log_write "${TICK} ${ftl_name}: ${COL_GREEN}${FTL_VERSION}${COL_NC}"
|
log_write "${TICK} ${ftl_name}: ${COL_GREEN}${FTL_VERSION}${COL_NC}"
|
||||||
else
|
else
|
||||||
# If not, show it in yellow, signifying there is an update
|
# If not, show it in yellow, signifying there is an update
|
||||||
log_write "${TICK} ${ftl_name}: ${COL_YELLOW}${FTL_VERSION}${COL_NC} (${FAQ_UPDATE_PI_HOLE})"
|
log_write "${INFO} ${ftl_name}: ${COL_YELLOW}${FTL_VERSION}${COL_NC} (${FAQ_UPDATE_PI_HOLE})"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# If they use the master branch, they are on the stable codebase
|
||||||
|
if [[ "${FTL_BRANCH}" == "master" ]]; then
|
||||||
|
# so the color of the text is green
|
||||||
|
log_write "${INFO} Branch: ${COL_GREEN}${FTL_BRANCH}${COL_NC}"
|
||||||
|
# If it is any other branch, they are in a development branch
|
||||||
|
else
|
||||||
|
# So show that in yellow, signifying it's something to take a look at, but not a critical error
|
||||||
|
log_write "${INFO} Branch: ${COL_YELLOW}${FTL_BRANCH}${COL_NC} (${FAQ_CHECKOUT_COMMAND})"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# echo the current commit
|
||||||
|
log_write "${INFO} Commit: ${FTL_COMMIT}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Checks the core version of the Pi-hole codebase
|
# Checks the core version of the Pi-hole codebase
|
||||||
@@ -467,8 +465,8 @@ diagnose_operating_system() {
|
|||||||
# Display the current test that is running
|
# Display the current test that is running
|
||||||
echo_current_diagnostic "Operating system"
|
echo_current_diagnostic "Operating system"
|
||||||
|
|
||||||
# If the PIHOLE_DOCKER_TAG variable is set, include this information in the debug output
|
# If DOCKER_VERSION is set (Sourced from /etc/pihole/versions at start of script), include this information in the debug output
|
||||||
[ -n "${PIHOLE_DOCKER_TAG}" ] && log_write "${INFO} Pi-hole Docker Container: ${PIHOLE_DOCKER_TAG}"
|
[ -n "${DOCKER_VERSION}" ] && log_write "${INFO} Pi-hole Docker Container: ${DOCKER_VERSION}"
|
||||||
|
|
||||||
# If there is a /etc/*release file, it's probably a supported operating system, so we can
|
# If there is a /etc/*release file, it's probably a supported operating system, so we can
|
||||||
if ls /etc/*release 1> /dev/null 2>&1; then
|
if ls /etc/*release 1> /dev/null 2>&1; then
|
||||||
@@ -600,10 +598,10 @@ disk_usage() {
|
|||||||
# Some lines of df might contain sensitive information like usernames and passwords.
|
# Some lines of df might contain sensitive information like usernames and passwords.
|
||||||
# E.g. curlftpfs filesystems (https://www.looklinux.com/mount-ftp-share-on-linux-using-curlftps/)
|
# E.g. curlftpfs filesystems (https://www.looklinux.com/mount-ftp-share-on-linux-using-curlftps/)
|
||||||
# We are not interested in those lines so we collect keyword, to remove them from the output
|
# We are not interested in those lines so we collect keyword, to remove them from the output
|
||||||
# Additinal keywords can be added, separated by "|"
|
# Additional keywords can be added, separated by "|"
|
||||||
hide="curlftpfs"
|
hide="curlftpfs"
|
||||||
|
|
||||||
# only show those lines not containg a sensitive phrase
|
# only show those lines not containing a sensitive phrase
|
||||||
for line in "${file_system[@]}"; do
|
for line in "${file_system[@]}"; do
|
||||||
if [[ ! $line =~ $hide ]]; then
|
if [[ ! $line =~ $hide ]]; then
|
||||||
log_write " ${line}"
|
log_write " ${line}"
|
||||||
@@ -678,15 +676,20 @@ ping_gateway() {
|
|||||||
local protocol="${1}"
|
local protocol="${1}"
|
||||||
ping_ipv4_or_ipv6 "${protocol}"
|
ping_ipv4_or_ipv6 "${protocol}"
|
||||||
# Check if we are using IPv4 or IPv6
|
# Check if we are using IPv4 or IPv6
|
||||||
# Find the default gateway using IPv4 or IPv6
|
# Find the default gateways using IPv4 or IPv6
|
||||||
local gateway
|
local gateway
|
||||||
gateway="$(ip -"${protocol}" route | grep default | grep "${PIHOLE_INTERFACE}" | cut -d ' ' -f 3)"
|
|
||||||
|
|
||||||
# If the gateway variable has a value (meaning a gateway was found),
|
log_write "${INFO} Default IPv${protocol} gateway(s):"
|
||||||
if [[ -n "${gateway}" ]]; then
|
|
||||||
log_write "${INFO} Default IPv${protocol} gateway: ${gateway}"
|
while IFS= read -r gateway; do
|
||||||
|
log_write " ${gateway}"
|
||||||
|
done < <(ip -"${protocol}" route | grep default | grep "${PIHOLE_INTERFACE}" | cut -d ' ' -f 3)
|
||||||
|
|
||||||
|
gateway=$(ip -"${protocol}" route | grep default | grep "${PIHOLE_INTERFACE}" | cut -d ' ' -f 3 | head -n 1)
|
||||||
|
# If there was at least one gateway
|
||||||
|
if [ -n "${gateway}" ]; then
|
||||||
# Let the user know we will ping the gateway for a response
|
# Let the user know we will ping the gateway for a response
|
||||||
log_write " * Pinging ${gateway}..."
|
log_write " * Pinging first gateway ${gateway}..."
|
||||||
# Try to quietly ping the gateway 3 times, with a timeout of 3 seconds, using numeric output only,
|
# Try to quietly ping the gateway 3 times, with a timeout of 3 seconds, using numeric output only,
|
||||||
# on the pihole interface, and tail the last three lines of the output
|
# on the pihole interface, and tail the last three lines of the output
|
||||||
# If pinging the gateway is not successful,
|
# If pinging the gateway is not successful,
|
||||||
@@ -753,7 +756,7 @@ check_required_ports() {
|
|||||||
# Sort the addresses and remove duplicates
|
# Sort the addresses and remove duplicates
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
ports_in_use+=( "$line" )
|
ports_in_use+=( "$line" )
|
||||||
done < <( ss --listening --numeric --tcp --udp --processes --oneline --no-header )
|
done < <( ss --listening --numeric --tcp --udp --processes --no-header )
|
||||||
|
|
||||||
# Now that we have the values stored,
|
# Now that we have the values stored,
|
||||||
for i in "${!ports_in_use[@]}"; do
|
for i in "${!ports_in_use[@]}"; do
|
||||||
@@ -779,6 +782,21 @@ check_required_ports() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip_command() {
|
||||||
|
# Obtain and log information from "ip XYZ show" commands
|
||||||
|
echo_current_diagnostic "${2}"
|
||||||
|
local entries=()
|
||||||
|
mapfile -t entries < <(ip "${1}" show)
|
||||||
|
for line in "${entries[@]}"; do
|
||||||
|
log_write " ${line}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ip_command() {
|
||||||
|
ip_command "addr" "Network interfaces and addresses"
|
||||||
|
ip_command "route" "Network routing table"
|
||||||
|
}
|
||||||
|
|
||||||
check_networking() {
|
check_networking() {
|
||||||
# Runs through several of the functions made earlier; we just clump them
|
# Runs through several of the functions made earlier; we just clump them
|
||||||
# together since they are all related to the networking aspect of things
|
# together since they are all related to the networking aspect of things
|
||||||
@@ -787,7 +805,9 @@ check_networking() {
|
|||||||
detect_ip_addresses "6"
|
detect_ip_addresses "6"
|
||||||
ping_gateway "4"
|
ping_gateway "4"
|
||||||
ping_gateway "6"
|
ping_gateway "6"
|
||||||
check_required_ports
|
# Skip the following check if installed in docker container. Unpriv'ed containers do not have access to the information required
|
||||||
|
# to resolve the service name listening - and the container should not start if there was a port conflict anyway
|
||||||
|
[ -z "${DOCKER_VERSION}" ] && check_required_ports
|
||||||
}
|
}
|
||||||
|
|
||||||
check_x_headers() {
|
check_x_headers() {
|
||||||
@@ -797,39 +817,24 @@ check_x_headers() {
|
|||||||
# Similarly, it will show "X-Pi-hole: The Pi-hole Web interface is working!" if you view the header returned
|
# Similarly, it will show "X-Pi-hole: The Pi-hole Web interface is working!" if you view the header returned
|
||||||
# when accessing the dashboard (i.e curl -I pi.hole/admin/)
|
# when accessing the dashboard (i.e curl -I pi.hole/admin/)
|
||||||
# server is operating correctly
|
# server is operating correctly
|
||||||
echo_current_diagnostic "Dashboard and block page"
|
echo_current_diagnostic "Dashboard headers"
|
||||||
# Use curl -I to get the header and parse out just the X-Pi-hole one
|
# Use curl -I to get the header and parse out just the X-Pi-hole one
|
||||||
local block_page
|
local full_curl_output_dashboard
|
||||||
block_page=$(curl -Is localhost | awk '/X-Pi-hole/' | tr -d '\r')
|
|
||||||
# Do it for the dashboard as well, as the header is different than above
|
|
||||||
local dashboard
|
local dashboard
|
||||||
dashboard=$(curl -Is localhost/admin/ | awk '/X-Pi-hole/' | tr -d '\r')
|
full_curl_output_dashboard="$(curl -Is localhost/admin/)"
|
||||||
|
dashboard=$(echo "${full_curl_output_dashboard}" | awk '/X-Pi-hole/' | tr -d '\r')
|
||||||
# Store what the X-Header should be in variables for comparison later
|
# Store what the X-Header should be in variables for comparison later
|
||||||
local block_page_working
|
|
||||||
block_page_working="X-Pi-hole: A black hole for Internet advertisements."
|
|
||||||
local dashboard_working
|
local dashboard_working
|
||||||
dashboard_working="X-Pi-hole: The Pi-hole Web interface is working!"
|
dashboard_working="X-Pi-hole: The Pi-hole Web interface is working!"
|
||||||
local full_curl_output_block_page
|
|
||||||
full_curl_output_block_page="$(curl -Is localhost)"
|
|
||||||
local full_curl_output_dashboard
|
|
||||||
full_curl_output_dashboard="$(curl -Is localhost/admin/)"
|
|
||||||
# If the X-header found by curl matches what is should be,
|
|
||||||
if [[ $block_page == "$block_page_working" ]]; then
|
|
||||||
# display a success message
|
|
||||||
log_write "$TICK Block page X-Header: ${COL_GREEN}${block_page}${COL_NC}"
|
|
||||||
else
|
|
||||||
# Otherwise, show an error
|
|
||||||
log_write "$CROSS Block page X-Header: ${COL_RED}X-Header does not match or could not be retrieved.${COL_NC}"
|
|
||||||
log_write "${COL_RED}${full_curl_output_block_page}${COL_NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Same logic applies to the dashboard as above, if the X-Header matches what a working system should have,
|
# If the X-Header matches what a working system should have,
|
||||||
if [[ $dashboard == "$dashboard_working" ]]; then
|
if [[ $dashboard == "$dashboard_working" ]]; then
|
||||||
# then we can show a success
|
# then we can show a success
|
||||||
log_write "$TICK Web interface X-Header: ${COL_GREEN}${dashboard}${COL_NC}"
|
log_write "$TICK Web interface X-Header: ${COL_GREEN}${dashboard}${COL_NC}"
|
||||||
else
|
else
|
||||||
# Otherwise, it's a failure since the X-Headers either don't exist or have been modified in some way
|
# Otherwise, it's a failure since the X-Headers either don't exist or have been modified in some way
|
||||||
log_write "$CROSS Web interface X-Header: ${COL_RED}X-Header does not match or could not be retrieved.${COL_NC}"
|
log_write "$CROSS Web interface X-Header: ${COL_RED}X-Header does not match or could not be retrieved.${COL_NC}"
|
||||||
|
|
||||||
log_write "${COL_RED}${full_curl_output_dashboard}${COL_NC}"
|
log_write "${COL_RED}${full_curl_output_dashboard}${COL_NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -871,7 +876,7 @@ dig_at() {
|
|||||||
# This helps emulate queries to different domains that a user might query
|
# This helps emulate queries to different domains that a user might query
|
||||||
# It will also give extra assurance that Pi-hole is correctly resolving and blocking domains
|
# It will also give extra assurance that Pi-hole is correctly resolving and blocking domains
|
||||||
local random_url
|
local random_url
|
||||||
random_url=$(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity ORDER BY RANDOM() LIMIT 1")
|
random_url=$(pihole-FTL sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity ORDER BY RANDOM() LIMIT 1")
|
||||||
|
|
||||||
# Next we need to check if Pi-hole can resolve a domain when the query is sent to it's IP address
|
# Next we need to check if Pi-hole can resolve a domain when the query is sent to it's IP address
|
||||||
# This better emulates how clients will interact with Pi-hole as opposed to above where Pi-hole is
|
# This better emulates how clients will interact with Pi-hole as opposed to above where Pi-hole is
|
||||||
@@ -889,9 +894,11 @@ dig_at() {
|
|||||||
# Removes all interfaces which are not UP
|
# Removes all interfaces which are not UP
|
||||||
# s/^[0-9]*: //g;
|
# s/^[0-9]*: //g;
|
||||||
# Removes interface index
|
# Removes interface index
|
||||||
|
# s/@.*//g;
|
||||||
|
# Removes everything after @ (if found)
|
||||||
# s/: <.*//g;
|
# s/: <.*//g;
|
||||||
# Removes everything after the interface name
|
# Removes everything after the interface name
|
||||||
interfaces="$(ip link show | sed "/ master /d;/UP/!d;s/^[0-9]*: //g;s/: <.*//g;")"
|
interfaces="$(ip link show | sed "/ master /d;/UP/!d;s/^[0-9]*: //g;s/@.*//g;s/: <.*//g;")"
|
||||||
|
|
||||||
while IFS= read -r iface ; do
|
while IFS= read -r iface ; do
|
||||||
# Get addresses of current interface
|
# Get addresses of current interface
|
||||||
@@ -990,7 +997,7 @@ make_array_from_file() {
|
|||||||
else
|
else
|
||||||
# Otherwise, read the file line by line
|
# Otherwise, read the file line by line
|
||||||
while IFS= read -r line;do
|
while IFS= read -r line;do
|
||||||
# Othwerise, strip out comments and blank lines
|
# Otherwise, strip out comments and blank lines
|
||||||
new_line=$(echo "${line}" | sed -e 's/^\s*#.*$//' -e '/^$/d')
|
new_line=$(echo "${line}" | sed -e 's/^\s*#.*$//' -e '/^$/d')
|
||||||
# If the line still has content (a non-zero value)
|
# If the line still has content (a non-zero value)
|
||||||
if [[ -n "${new_line}" ]]; then
|
if [[ -n "${new_line}" ]]; then
|
||||||
@@ -1048,7 +1055,7 @@ parse_file() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_name_resolution() {
|
check_name_resolution() {
|
||||||
# Check name resolution from localhost, Pi-hole's IP, and Google's name severs
|
# Check name resolution from localhost, Pi-hole's IP, and Google's name servers
|
||||||
# using the function we created earlier
|
# using the function we created earlier
|
||||||
dig_at 4
|
dig_at 4
|
||||||
dig_at 6
|
dig_at 6
|
||||||
@@ -1185,7 +1192,7 @@ show_db_entries() {
|
|||||||
IFS=$'\r\n'
|
IFS=$'\r\n'
|
||||||
local entries=()
|
local entries=()
|
||||||
mapfile -t entries < <(\
|
mapfile -t entries < <(\
|
||||||
sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" \
|
pihole-FTL sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" \
|
||||||
-cmd ".headers on" \
|
-cmd ".headers on" \
|
||||||
-cmd ".mode column" \
|
-cmd ".mode column" \
|
||||||
-cmd ".width ${widths}" \
|
-cmd ".width ${widths}" \
|
||||||
@@ -1210,7 +1217,7 @@ show_FTL_db_entries() {
|
|||||||
IFS=$'\r\n'
|
IFS=$'\r\n'
|
||||||
local entries=()
|
local entries=()
|
||||||
mapfile -t entries < <(\
|
mapfile -t entries < <(\
|
||||||
sqlite3 "${PIHOLE_FTL_DB_FILE}" \
|
pihole-FTL sqlite3 "${PIHOLE_FTL_DB_FILE}" \
|
||||||
-cmd ".headers on" \
|
-cmd ".headers on" \
|
||||||
-cmd ".mode column" \
|
-cmd ".mode column" \
|
||||||
-cmd ".width ${widths}" \
|
-cmd ".width ${widths}" \
|
||||||
@@ -1230,7 +1237,7 @@ check_dhcp_servers() {
|
|||||||
OLD_IFS="$IFS"
|
OLD_IFS="$IFS"
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
local entries=()
|
local entries=()
|
||||||
mapfile -t entries < <(pihole-FTL dhcp-discover)
|
mapfile -t entries < <(pihole-FTL dhcp-discover & spinner)
|
||||||
|
|
||||||
for line in "${entries[@]}"; do
|
for line in "${entries[@]}"; do
|
||||||
log_write " ${line}"
|
log_write " ${line}"
|
||||||
@@ -1256,18 +1263,27 @@ show_clients() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
show_messages() {
|
show_messages() {
|
||||||
show_FTL_db_entries "Pi-hole diagnosis messages" "SELECT id,datetime(timestamp,'unixepoch','localtime') timestamp,type,message,blob1,blob2,blob3,blob4,blob5 FROM message;" "4 19 20 60 20 20 20 20 20"
|
show_FTL_db_entries "Pi-hole diagnosis messages" "SELECT count (message) as count, datetime(max(timestamp),'unixepoch','localtime') as 'last timestamp', type, message, blob1, blob2, blob3, blob4, blob5 FROM message GROUP BY type, message, blob1, blob2, blob3, blob4, blob5;" "6 19 20 60 20 20 20 20 20"
|
||||||
|
}
|
||||||
|
|
||||||
|
database_permissions() {
|
||||||
|
local permissions
|
||||||
|
permissions=$(ls -lhd "${1}")
|
||||||
|
log_write "${COL_GREEN}${permissions}${COL_NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze_gravity_list() {
|
analyze_gravity_list() {
|
||||||
echo_current_diagnostic "Gravity Database"
|
echo_current_diagnostic "Gravity Database"
|
||||||
|
|
||||||
local gravity_permissions
|
database_permissions "${PIHOLE_GRAVITY_DB_FILE}"
|
||||||
gravity_permissions=$(ls -lhd "${PIHOLE_GRAVITY_DB_FILE}")
|
|
||||||
log_write "${COL_GREEN}${gravity_permissions}${COL_NC}"
|
# if users want to check database integrity
|
||||||
|
if [[ "${CHECK_DATABASE}" = true ]]; then
|
||||||
|
database_integrity_check "${PIHOLE_GRAVITY_DB_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
show_db_entries "Info table" "SELECT property,value FROM info" "20 40"
|
show_db_entries "Info table" "SELECT property,value FROM info" "20 40"
|
||||||
gravity_updated_raw="$(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT value FROM info where property = 'updated'")"
|
gravity_updated_raw="$(pihole-FTL sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT value FROM info where property = 'updated'")"
|
||||||
gravity_updated="$(date -d @"${gravity_updated_raw}")"
|
gravity_updated="$(date -d @"${gravity_updated_raw}")"
|
||||||
log_write " Last gravity run finished at: ${COL_CYAN}${gravity_updated}${COL_NC}"
|
log_write " Last gravity run finished at: ${COL_CYAN}${gravity_updated}${COL_NC}"
|
||||||
log_write ""
|
log_write ""
|
||||||
@@ -1275,7 +1291,7 @@ analyze_gravity_list() {
|
|||||||
OLD_IFS="$IFS"
|
OLD_IFS="$IFS"
|
||||||
IFS=$'\r\n'
|
IFS=$'\r\n'
|
||||||
local gravity_sample=()
|
local gravity_sample=()
|
||||||
mapfile -t gravity_sample < <(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity LIMIT 10")
|
mapfile -t gravity_sample < <(pihole-FTL sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity LIMIT 10")
|
||||||
log_write " ${COL_CYAN}----- First 10 Gravity Domains -----${COL_NC}"
|
log_write " ${COL_CYAN}----- First 10 Gravity Domains -----${COL_NC}"
|
||||||
|
|
||||||
for line in "${gravity_sample[@]}"; do
|
for line in "${gravity_sample[@]}"; do
|
||||||
@@ -1286,6 +1302,85 @@ analyze_gravity_list() {
|
|||||||
IFS="$OLD_IFS"
|
IFS="$OLD_IFS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
analyze_ftl_db() {
|
||||||
|
echo_current_diagnostic "Pi-hole FTL Query Database"
|
||||||
|
database_permissions "${PIHOLE_FTL_DB_FILE}"
|
||||||
|
# if users want to check database integrity
|
||||||
|
if [[ "${CHECK_DATABASE}" = true ]]; then
|
||||||
|
database_integrity_check "${PIHOLE_FTL_DB_FILE}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
database_integrity_check(){
|
||||||
|
local result
|
||||||
|
local database="${1}"
|
||||||
|
|
||||||
|
log_write "${INFO} Checking integrity of ${database} ... (this can take several minutes)"
|
||||||
|
result="$(pihole-FTL "${database}" "PRAGMA integrity_check" 2>&1 & spinner)"
|
||||||
|
if [[ ${result} = "ok" ]]; then
|
||||||
|
log_write "${TICK} Integrity of ${database} intact"
|
||||||
|
|
||||||
|
|
||||||
|
log_write "${INFO} Checking foreign key constraints of ${database} ... (this can take several minutes)"
|
||||||
|
unset result
|
||||||
|
result="$(pihole-FTL sqlite3 "${database}" -cmd ".headers on" -cmd ".mode column" "PRAGMA foreign_key_check" 2>&1 & spinner)"
|
||||||
|
if [[ -z ${result} ]]; then
|
||||||
|
log_write "${TICK} No foreign key errors in ${database}"
|
||||||
|
else
|
||||||
|
log_write "${CROSS} ${COL_RED}Foreign key errors in ${database} found.${COL_NC}"
|
||||||
|
while IFS= read -r line ; do
|
||||||
|
log_write " $line"
|
||||||
|
done <<< "$result"
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
log_write "${CROSS} ${COL_RED}Integrity errors in ${database} found.\n${COL_NC}"
|
||||||
|
while IFS= read -r line ; do
|
||||||
|
log_write " $line"
|
||||||
|
done <<< "$result"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show a text spinner during a long process run
|
||||||
|
spinner(){
|
||||||
|
# Show the spinner only if there is a tty
|
||||||
|
if tty -s; then
|
||||||
|
# PID of the most recent background process
|
||||||
|
_PID=$!
|
||||||
|
_spin="/-\|"
|
||||||
|
_start=0
|
||||||
|
_elapsed=0
|
||||||
|
_i=1
|
||||||
|
|
||||||
|
# Start the counter
|
||||||
|
_start=$(date +%s)
|
||||||
|
|
||||||
|
# Hide the cursor
|
||||||
|
tput civis > /dev/tty
|
||||||
|
|
||||||
|
# ensures cursor is visible again, in case of premature exit
|
||||||
|
trap 'tput cnorm > /dev/tty' EXIT
|
||||||
|
|
||||||
|
while [ -d /proc/$_PID ]; do
|
||||||
|
_elapsed=$(( $(date +%s) - _start ))
|
||||||
|
# use hours only if needed
|
||||||
|
if [ "$_elapsed" -lt 3600 ]; then
|
||||||
|
printf "\r${_spin:_i++%${#_spin}:1} %02d:%02d" $((_elapsed/60)) $((_elapsed%60)) >"$(tty)"
|
||||||
|
else
|
||||||
|
printf "\r${_spin:_i++%${#_spin}:1} %02d:%02d:%02d" $((_elapsed/3600)) $(((_elapsed/60)%60)) $((_elapsed%60)) >"$(tty)"
|
||||||
|
fi
|
||||||
|
sleep 0.25
|
||||||
|
done
|
||||||
|
|
||||||
|
# Return to the begin of the line after completion (the spinner will be overwritten)
|
||||||
|
printf "\r" >"$(tty)"
|
||||||
|
|
||||||
|
# Restore cursor visibility
|
||||||
|
tput cnorm > /dev/tty
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
obfuscated_pihole_log() {
|
obfuscated_pihole_log() {
|
||||||
local pihole_log=("$@")
|
local pihole_log=("$@")
|
||||||
local line
|
local line
|
||||||
@@ -1309,7 +1404,7 @@ obfuscated_pihole_log() {
|
|||||||
# If the variable does not a value (the current default behavior), so do not obfuscate anything
|
# If the variable does not a value (the current default behavior), so do not obfuscate anything
|
||||||
if [[ -z ${OBFUSCATE} ]]; then
|
if [[ -z ${OBFUSCATE} ]]; then
|
||||||
log_write " ${line}"
|
log_write " ${line}"
|
||||||
# Othwerise, a flag was passed to this command to obfuscate domains in the log
|
# Otherwise, a flag was passed to this command to obfuscate domains in the log
|
||||||
else
|
else
|
||||||
# So first check if there are domains in the log that should be obfuscated
|
# So first check if there are domains in the log that should be obfuscated
|
||||||
if [[ -n ${line_to_obfuscate} ]]; then
|
if [[ -n ${line_to_obfuscate} ]]; then
|
||||||
@@ -1375,7 +1470,7 @@ curl_to_tricorder() {
|
|||||||
upload_to_tricorder() {
|
upload_to_tricorder() {
|
||||||
local username="pihole"
|
local username="pihole"
|
||||||
# Set the permissions and owner
|
# Set the permissions and owner
|
||||||
chmod 644 ${PIHOLE_DEBUG_LOG}
|
chmod 640 ${PIHOLE_DEBUG_LOG}
|
||||||
chown "$USER":"${username}" ${PIHOLE_DEBUG_LOG}
|
chown "$USER":"${username}" ${PIHOLE_DEBUG_LOG}
|
||||||
|
|
||||||
# Let the user know debugging is complete with something strikingly visual
|
# Let the user know debugging is complete with something strikingly visual
|
||||||
@@ -1431,7 +1526,7 @@ upload_to_tricorder() {
|
|||||||
if [[ "${WEBCALL}" ]] && [[ ! "${AUTOMATED}" ]]; then
|
if [[ "${WEBCALL}" ]] && [[ ! "${AUTOMATED}" ]]; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
log_write "${CROSS} ${COL_RED}There was an error uploading your debug log.${COL_NC}"
|
log_write "${CROSS} ${COL_RED}There was an error uploading your debug log.${COL_NC}"
|
||||||
log_write " * Please try again or contact the Pi-hole team for assistance."
|
log_write " * Please try again or contact the Pi-hole team for assistance."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -1452,6 +1547,7 @@ check_selinux
|
|||||||
check_firewalld
|
check_firewalld
|
||||||
processor_check
|
processor_check
|
||||||
disk_usage
|
disk_usage
|
||||||
|
check_ip_command
|
||||||
check_networking
|
check_networking
|
||||||
check_name_resolution
|
check_name_resolution
|
||||||
check_dhcp_servers
|
check_dhcp_servers
|
||||||
@@ -1459,6 +1555,7 @@ process_status
|
|||||||
ftl_full_status
|
ftl_full_status
|
||||||
parse_setup_vars
|
parse_setup_vars
|
||||||
check_x_headers
|
check_x_headers
|
||||||
|
analyze_ftl_db
|
||||||
analyze_gravity_list
|
analyze_gravity_list
|
||||||
show_groups
|
show_groups
|
||||||
show_domainlist
|
show_domainlist
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ if [ -z "$DBFILE" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$@" != *"quiet"* ]]; then
|
if [[ "$@" != *"quiet"* ]]; then
|
||||||
echo -ne " ${INFO} Flushing /var/log/pihole.log ..."
|
echo -ne " ${INFO} Flushing /var/log/pihole/pihole.log ..."
|
||||||
fi
|
fi
|
||||||
if [[ "$@" == *"once"* ]]; then
|
if [[ "$@" == *"once"* ]]; then
|
||||||
# Nightly logrotation
|
# Nightly logrotation
|
||||||
@@ -44,9 +44,9 @@ if [[ "$@" == *"once"* ]]; then
|
|||||||
# Note that moving the file is not an option, as
|
# Note that moving the file is not an option, as
|
||||||
# dnsmasq would happily continue writing into the
|
# dnsmasq would happily continue writing into the
|
||||||
# moved file (it will have the same file handler)
|
# moved file (it will have the same file handler)
|
||||||
cp -p /var/log/pihole.log /var/log/pihole.log.1
|
cp -p /var/log/pihole/pihole.log /var/log/pihole/pihole.log.1
|
||||||
echo " " > /var/log/pihole.log
|
echo " " > /var/log/pihole/pihole.log
|
||||||
chmod 644 /var/log/pihole.log
|
chmod 640 /var/log/pihole/pihole.log
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Manual flushing
|
# Manual flushing
|
||||||
@@ -56,20 +56,20 @@ else
|
|||||||
/usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate
|
/usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate
|
||||||
else
|
else
|
||||||
# Flush both pihole.log and pihole.log.1 (if existing)
|
# Flush both pihole.log and pihole.log.1 (if existing)
|
||||||
echo " " > /var/log/pihole.log
|
echo " " > /var/log/pihole/pihole.log
|
||||||
if [ -f /var/log/pihole.log.1 ]; then
|
if [ -f /var/log/pihole/pihole.log.1 ]; then
|
||||||
echo " " > /var/log/pihole.log.1
|
echo " " > /var/log/pihole/pihole.log.1
|
||||||
chmod 644 /var/log/pihole.log.1
|
chmod 640 /var/log/pihole/pihole.log.1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
|
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
|
||||||
deleted=$(sqlite3 "${DBFILE}" "DELETE FROM queries WHERE timestamp >= strftime('%s','now')-86400; select changes() from queries limit 1")
|
deleted=$(pihole-FTL sqlite3 "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1")
|
||||||
|
|
||||||
# Restart pihole-FTL to force reloading history
|
# Restart pihole-FTL to force reloading history
|
||||||
sudo pihole restartdns
|
sudo pihole restartdns
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$@" != *"quiet"* ]]; then
|
if [[ "$@" != *"quiet"* ]]; then
|
||||||
echo -e "${OVER} ${TICK} Flushed /var/log/pihole.log"
|
echo -e "${OVER} ${TICK} Flushed /var/log/pihole/pihole.log"
|
||||||
echo -e " ${TICK} Deleted ${deleted} queries from database"
|
echo -e " ${TICK} Deleted ${deleted} queries from database"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ GRAVITYDB="${piholeDir}/gravity.db"
|
|||||||
options="$*"
|
options="$*"
|
||||||
all=""
|
all=""
|
||||||
exact=""
|
exact=""
|
||||||
blockpage=""
|
|
||||||
matchType="match"
|
matchType="match"
|
||||||
# Source pihole-FTL from install script
|
# Source pihole-FTL from install script
|
||||||
pihole_FTL="${piholeDir}/pihole-FTL.conf"
|
pihole_FTL="${piholeDir}/pihole-FTL.conf"
|
||||||
@@ -34,7 +33,7 @@ source "${colfile}"
|
|||||||
# Scan an array of files for matching strings
|
# Scan an array of files for matching strings
|
||||||
scanList(){
|
scanList(){
|
||||||
# Escape full stops
|
# Escape full stops
|
||||||
local domain="${1}" esc_domain="${1//./\\.}" lists="${2}" type="${3:-}"
|
local domain="${1}" esc_domain="${1//./\\.}" lists="${2}" list_type="${3:-}"
|
||||||
|
|
||||||
# Prevent grep from printing file path
|
# Prevent grep from printing file path
|
||||||
cd "$piholeDir" || exit 1
|
cd "$piholeDir" || exit 1
|
||||||
@@ -43,7 +42,7 @@ scanList(){
|
|||||||
export LC_CTYPE=C
|
export LC_CTYPE=C
|
||||||
|
|
||||||
# /dev/null forces filename to be printed when only one list has been generated
|
# /dev/null forces filename to be printed when only one list has been generated
|
||||||
case "${type}" in
|
case "${list_type}" in
|
||||||
"exact" ) grep -i -E -l "(^|(?<!#)\\s)${esc_domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
|
"exact" ) grep -i -E -l "(^|(?<!#)\\s)${esc_domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
|
||||||
# Iterate through each regexp and check whether it matches the domainQuery
|
# Iterate through each regexp and check whether it matches the domainQuery
|
||||||
# If it does, print the matching regexp and continue looping
|
# If it does, print the matching regexp and continue looping
|
||||||
@@ -64,25 +63,21 @@ Example: 'pihole -q -exact domain.com'
|
|||||||
Query the adlists for a specified domain
|
Query the adlists for a specified domain
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-exact Search the block lists for exact domain matches
|
-exact Search the adlists for exact domain matches
|
||||||
-all Return all query matches within a block list
|
-all Return all query matches within the adlists
|
||||||
-h, --help Show this help dialog"
|
-h, --help Show this help dialog"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Handle valid options
|
# Handle valid options
|
||||||
if [[ "${options}" == *"-bp"* ]]; then
|
[[ "${options}" == *"-all"* ]] && all=true
|
||||||
exact="exact"; blockpage=true
|
if [[ "${options}" == *"-exact"* ]]; then
|
||||||
else
|
exact="exact"; matchType="exact ${matchType}"
|
||||||
[[ "${options}" == *"-all"* ]] && all=true
|
|
||||||
if [[ "${options}" == *"-exact"* ]]; then
|
|
||||||
exact="exact"; matchType="exact ${matchType}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Strip valid options, leaving only the domain and invalid options
|
# Strip valid options, leaving only the domain and invalid options
|
||||||
# This allows users to place the options before or after the domain
|
# This allows users to place the options before or after the domain
|
||||||
options=$(sed -E 's/ ?-(bp|adlists?|all|exact) ?//g' <<< "${options}")
|
options=$(sed -E 's/ ?-(adlists?|all|exact) ?//g' <<< "${options}")
|
||||||
|
|
||||||
# Handle remaining options
|
# Handle remaining options
|
||||||
# If $options contain non ASCII characters, convert to punycode
|
# If $options contain non ASCII characters, convert to punycode
|
||||||
@@ -99,10 +94,10 @@ if [[ -n "${str:-}" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
scanDatabaseTable() {
|
scanDatabaseTable() {
|
||||||
local domain table type querystr result extra
|
local domain table list_type querystr result extra
|
||||||
domain="$(printf "%q" "${1}")"
|
domain="$(printf "%q" "${1}")"
|
||||||
table="${2}"
|
table="${2}"
|
||||||
type="${3:-}"
|
list_type="${3:-}"
|
||||||
|
|
||||||
# As underscores are legitimate parts of domains, we escape them when using the LIKE operator.
|
# As underscores are legitimate parts of domains, we escape them when using the LIKE operator.
|
||||||
# Underscores are SQLite wildcards matching exactly one character. We obviously want to suppress this
|
# Underscores are SQLite wildcards matching exactly one character. We obviously want to suppress this
|
||||||
@@ -115,13 +110,13 @@ scanDatabaseTable() {
|
|||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
case "${exact}" in
|
case "${exact}" in
|
||||||
"exact" ) querystr="SELECT domain,enabled FROM domainlist WHERE type = '${type}' AND domain = '${domain}'";;
|
"exact" ) querystr="SELECT domain,enabled FROM domainlist WHERE type = '${list_type}' AND domain = '${domain}'";;
|
||||||
* ) querystr="SELECT domain,enabled FROM domainlist WHERE type = '${type}' AND domain LIKE '%${domain//_/\\_}%' ESCAPE '\\'";;
|
* ) querystr="SELECT domain,enabled FROM domainlist WHERE type = '${list_type}' AND domain LIKE '%${domain//_/\\_}%' ESCAPE '\\'";;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Send prepared query to gravity database
|
# Send prepared query to gravity database
|
||||||
result="$(sqlite3 "${gravityDBfile}" "${querystr}")" 2> /dev/null
|
result="$(pihole-FTL sqlite3 "${gravityDBfile}" "${querystr}")" 2> /dev/null
|
||||||
if [[ -z "${result}" ]]; then
|
if [[ -z "${result}" ]]; then
|
||||||
# Return early when there are no matches in this table
|
# Return early when there are no matches in this table
|
||||||
return
|
return
|
||||||
@@ -136,17 +131,11 @@ scanDatabaseTable() {
|
|||||||
wbMatch=true
|
wbMatch=true
|
||||||
|
|
||||||
# Print table name
|
# Print table name
|
||||||
if [[ -z "${blockpage}" ]]; then
|
echo " ${matchType^} found in ${COL_BOLD}exact ${table}${COL_NC}"
|
||||||
echo " ${matchType^} found in ${COL_BOLD}exact ${table}${COL_NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Loop over results and print them
|
# Loop over results and print them
|
||||||
mapfile -t results <<< "${result}"
|
mapfile -t results <<< "${result}"
|
||||||
for result in "${results[@]}"; do
|
for result in "${results[@]}"; do
|
||||||
if [[ -n "${blockpage}" ]]; then
|
|
||||||
echo "π ${result}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
domain="${result/|*}"
|
domain="${result/|*}"
|
||||||
if [[ "${result#*|}" == "0" ]]; then
|
if [[ "${result#*|}" == "0" ]]; then
|
||||||
extra=" (disabled)"
|
extra=" (disabled)"
|
||||||
@@ -158,13 +147,13 @@ scanDatabaseTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanRegexDatabaseTable() {
|
scanRegexDatabaseTable() {
|
||||||
local domain list
|
local domain list list_type
|
||||||
domain="${1}"
|
domain="${1}"
|
||||||
list="${2}"
|
list="${2}"
|
||||||
type="${3:-}"
|
list_type="${3:-}"
|
||||||
|
|
||||||
# Query all regex from the corresponding database tables
|
# Query all regex from the corresponding database tables
|
||||||
mapfile -t regexList < <(sqlite3 "${gravityDBfile}" "SELECT domain FROM domainlist WHERE type = ${type}" 2> /dev/null)
|
mapfile -t regexList < <(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT domain FROM domainlist WHERE type = ${list_type}" 2> /dev/null)
|
||||||
|
|
||||||
# If we have regexps to process
|
# If we have regexps to process
|
||||||
if [[ "${#regexList[@]}" -ne 0 ]]; then
|
if [[ "${#regexList[@]}" -ne 0 ]]; then
|
||||||
@@ -181,18 +170,13 @@ scanRegexDatabaseTable() {
|
|||||||
# Form a "results" message
|
# Form a "results" message
|
||||||
str_result="${COL_BOLD}${str_regexMatches}${COL_NC}"
|
str_result="${COL_BOLD}${str_regexMatches}${COL_NC}"
|
||||||
# If we are displaying more than just the source of the block
|
# If we are displaying more than just the source of the block
|
||||||
if [[ -z "${blockpage}" ]]; then
|
# Set the wildcard match flag
|
||||||
# Set the wildcard match flag
|
wcMatch=true
|
||||||
wcMatch=true
|
# Echo the "matched" message, indented by one space
|
||||||
# Echo the "matched" message, indented by one space
|
echo " ${str_message}"
|
||||||
echo " ${str_message}"
|
# Echo the "results" message, each line indented by three spaces
|
||||||
# Echo the "results" message, each line indented by three spaces
|
# shellcheck disable=SC2001
|
||||||
# shellcheck disable=SC2001
|
echo "${str_result}" | sed 's/^/ /'
|
||||||
echo "${str_result}" | sed 's/^/ /'
|
|
||||||
else
|
|
||||||
echo "π .wildcard"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -210,7 +194,7 @@ mapfile -t results <<< "$(scanDatabaseTable "${domainQuery}" "gravity")"
|
|||||||
|
|
||||||
# Handle notices
|
# Handle notices
|
||||||
if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then
|
if [[ -z "${wbMatch:-}" ]] && [[ -z "${wcMatch:-}" ]] && [[ -z "${results[*]}" ]]; then
|
||||||
echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the block lists"
|
echo -e " ${INFO} No ${exact/t/t }results found for ${COL_BOLD}${domainQuery}${COL_NC} within the adlists"
|
||||||
exit 0
|
exit 0
|
||||||
elif [[ -z "${results[*]}" ]]; then
|
elif [[ -z "${results[*]}" ]]; then
|
||||||
# Result found in WL/BL/Wildcards
|
# Result found in WL/BL/Wildcards
|
||||||
@@ -222,7 +206,7 @@ elif [[ -z "${all}" ]] && [[ "${#results[*]}" -ge 100 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Print "Exact matches for" title
|
# Print "Exact matches for" title
|
||||||
if [[ -n "${exact}" ]] && [[ -z "${blockpage}" ]]; then
|
if [[ -n "${exact}" ]]; then
|
||||||
plural=""; [[ "${#results[*]}" -gt 1 ]] && plural="es"
|
plural=""; [[ "${#results[*]}" -gt 1 ]] && plural="es"
|
||||||
echo " ${matchType^}${plural} for ${COL_BOLD}${domainQuery}${COL_NC} found in:"
|
echo " ${matchType^}${plural} for ${COL_BOLD}${domainQuery}${COL_NC} found in:"
|
||||||
fi
|
fi
|
||||||
@@ -233,15 +217,13 @@ for result in "${results[@]}"; do
|
|||||||
adlistAddress="${extra/|*/}"
|
adlistAddress="${extra/|*/}"
|
||||||
extra="${extra#*|}"
|
extra="${extra#*|}"
|
||||||
if [[ "${extra}" == "0" ]]; then
|
if [[ "${extra}" == "0" ]]; then
|
||||||
extra="(disabled)"
|
extra=" (disabled)"
|
||||||
else
|
else
|
||||||
extra=""
|
extra=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${blockpage}" ]]; then
|
if [[ -n "${exact}" ]]; then
|
||||||
echo "0 ${adlistAddress}"
|
echo " - ${adlistAddress}${extra}"
|
||||||
elif [[ -n "${exact}" ]]; then
|
|
||||||
echo " - ${adlistAddress} ${extra}"
|
|
||||||
else
|
else
|
||||||
if [[ ! "${adlistAddress}" == "${adlistAddress_prev:-}" ]]; then
|
if [[ ! "${adlistAddress}" == "${adlistAddress_prev:-}" ]]; then
|
||||||
count=""
|
count=""
|
||||||
@@ -256,7 +238,7 @@ for result in "${results[@]}"; do
|
|||||||
[[ "${count}" -gt "${max_count}" ]] && continue
|
[[ "${count}" -gt "${max_count}" ]] && continue
|
||||||
echo " ${COL_GRAY}Over ${count} results found, skipping rest of file${COL_NC}"
|
echo " ${COL_GRAY}Over ${count} results found, skipping rest of file${COL_NC}"
|
||||||
else
|
else
|
||||||
echo " ${match} ${extra}"
|
echo " ${match}${extra}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Pi-hole: A black hole for Internet advertisements
|
|
||||||
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
|
||||||
# Network-wide ad blocking via your own hardware.
|
|
||||||
#
|
|
||||||
# Automatically configures the Pi to use the 2.8 LCD screen to display stats on it (also works over ssh)
|
|
||||||
#
|
|
||||||
# This file is copyright under the latest version of the EUPL.
|
|
||||||
# Please see LICENSE file for your rights under this license.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############ FUNCTIONS ###########
|
|
||||||
|
|
||||||
# Borrowed from adafruit-pitft-helper < borrowed from raspi-config
|
|
||||||
# https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L324-L334
|
|
||||||
getInitSys() {
|
|
||||||
if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
|
|
||||||
SYSTEMD=1
|
|
||||||
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
|
|
||||||
SYSTEMD=0
|
|
||||||
else
|
|
||||||
echo "Unrecognized init system"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Borrowed from adafruit-pitft-helper:
|
|
||||||
# https://github.com/adafruit/Adafruit-PiTFT-Helper/blob/master/adafruit-pitft-helper#L274-L285
|
|
||||||
autoLoginPiToConsole() {
|
|
||||||
if [ -e /etc/init.d/lightdm ]; then
|
|
||||||
if [ ${SYSTEMD} -eq 1 ]; then
|
|
||||||
systemctl set-default multi-user.target
|
|
||||||
ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
|
|
||||||
else
|
|
||||||
update-rc.d lightdm disable 2
|
|
||||||
sed /etc/inittab -i -e "s/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/1:2345:respawn:\/bin\/login -f pi tty1 <\/dev\/tty1 >\/dev\/tty1 2>&1/"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
######### SCRIPT ###########
|
|
||||||
# Set pi to log in automatically
|
|
||||||
getInitSys
|
|
||||||
autoLoginPiToConsole
|
|
||||||
|
|
||||||
# Set chronomter to run automatically when pi logs in
|
|
||||||
echo /usr/local/bin/chronometer.sh >> /home/pi/.bashrc
|
|
||||||
# OR
|
|
||||||
#$SUDO echo /usr/local/bin/chronometer.sh >> /etc/profile
|
|
||||||
|
|
||||||
# Set up the LCD screen based on Adafruits instuctions:
|
|
||||||
# https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/easy-install
|
|
||||||
curl -SLs https://apt.adafruit.com/add-pin | bash
|
|
||||||
apt-get -y install raspberrypi-bootloader
|
|
||||||
apt-get -y install adafruit-pitft-helper
|
|
||||||
adafruit-pitft-helper -t 28r
|
|
||||||
|
|
||||||
# Download the cmdline.txt file that prevents the screen from going blank after a period of time
|
|
||||||
mv /boot/cmdline.txt /boot/cmdline.orig
|
|
||||||
curl -o /boot/cmdline.txt https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/cmdline.txt
|
|
||||||
|
|
||||||
# Back up the original file and download the new one
|
|
||||||
mv /etc/default/console-setup /etc/default/console-setup.orig
|
|
||||||
curl -o /etc/default/console-setup https://raw.githubusercontent.com/pi-hole/pi-hole/master/advanced/console-setup
|
|
||||||
|
|
||||||
# Instantly apply the font change to the LCD screen
|
|
||||||
setupcon
|
|
||||||
|
|
||||||
reboot
|
|
||||||
|
|
||||||
# Start showing the stats on the screen by running the command on another tty:
|
|
||||||
# https://unix.stackexchange.com/questions/170063/start-a-process-on-a-different-tty
|
|
||||||
#setsid sh -c 'exec /usr/local/bin/chronometer.sh <> /dev/tty1 >&0 2>&1'
|
|
||||||
@@ -17,7 +17,7 @@ readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git"
|
|||||||
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
PH_TEST=true
|
SKIP_INSTALL=true
|
||||||
|
|
||||||
# when --check-only is passed to this script, it will not perform the actual update
|
# when --check-only is passed to this script, it will not perform the actual update
|
||||||
CHECK_ONLY=false
|
CHECK_ONLY=false
|
||||||
@@ -41,7 +41,7 @@ GitCheckUpdateAvail() {
|
|||||||
cd "${directory}" || return
|
cd "${directory}" || return
|
||||||
|
|
||||||
# Fetch latest changes in this repo
|
# Fetch latest changes in this repo
|
||||||
git fetch --tags --quiet origin
|
git fetch --quiet origin
|
||||||
|
|
||||||
# Check current branch. If it is master, then check for the latest available tag instead of latest commit.
|
# Check current branch. If it is master, then check for the latest available tag instead of latest commit.
|
||||||
curBranch=$(git rev-parse --abbrev-ref HEAD)
|
curBranch=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
|||||||
@@ -8,23 +8,6 @@
|
|||||||
# This file is copyright under the latest version of the EUPL.
|
# This file is copyright under the latest version of the EUPL.
|
||||||
# Please see LICENSE file for your rights under this license.
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
# Credit: https://stackoverflow.com/a/46324904
|
|
||||||
function json_extract() {
|
|
||||||
local key=$1
|
|
||||||
local json=$2
|
|
||||||
|
|
||||||
local string_regex='"([^"\]|\\.)*"'
|
|
||||||
local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
|
|
||||||
local value_regex="${string_regex}|${number_regex}|true|false|null"
|
|
||||||
local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"
|
|
||||||
|
|
||||||
if [[ ${json} =~ ${pair_regex} ]]; then
|
|
||||||
echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_local_branch() {
|
function get_local_branch() {
|
||||||
# Return active branch
|
# Return active branch
|
||||||
cd "${1}" 2> /dev/null || return 1
|
cd "${1}" 2> /dev/null || return 1
|
||||||
@@ -41,54 +24,76 @@ function get_local_version() {
|
|||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. /etc/pihole/setupVars.conf
|
. /etc/pihole/setupVars.conf
|
||||||
|
|
||||||
|
# Source the utils file
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /opt/pihole/utils.sh
|
||||||
|
|
||||||
|
# Remove the below three legacy files if they exist
|
||||||
|
rm -f "/etc/pihole/GitHubVersions"
|
||||||
|
rm -f "/etc/pihole/localbranches"
|
||||||
|
rm -f "/etc/pihole/localversions"
|
||||||
|
|
||||||
|
# Create new versions file if it does not exist
|
||||||
|
VERSION_FILE="/etc/pihole/versions"
|
||||||
|
touch "${VERSION_FILE}"
|
||||||
|
chmod 644 "${VERSION_FILE}"
|
||||||
|
|
||||||
|
# if /pihole.docker.tag file exists, we will use it's value later in this script
|
||||||
|
DOCKER_TAG=$(cat /pihole.docker.tag 2>/dev/null)
|
||||||
|
regex='^([0-9]+\.){1,2}(\*|[0-9]+)(-.*)?$|(^nightly$)|(^dev.*$)'
|
||||||
|
if [[ ! "${DOCKER_TAG}" =~ $regex ]]; then
|
||||||
|
# DOCKER_TAG does not match the pattern (see https://regex101.com/r/RsENuz/1), so unset it.
|
||||||
|
unset DOCKER_TAG
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$2" == "remote" ]]; then
|
if [[ "$2" == "remote" ]]; then
|
||||||
|
|
||||||
if [[ "$3" == "reboot" ]]; then
|
if [[ "$3" == "reboot" ]]; then
|
||||||
sleep 30
|
sleep 30
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GITHUB_VERSION_FILE="/etc/pihole/GitHubVersions"
|
GITHUB_CORE_VERSION="$(curl -s 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null | jq --raw-output .tag_name)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_CORE_VERSION" "${GITHUB_CORE_VERSION}"
|
||||||
GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")"
|
|
||||||
echo -n "${GITHUB_CORE_VERSION}" > "${GITHUB_VERSION_FILE}"
|
|
||||||
chmod 644 "${GITHUB_VERSION_FILE}"
|
|
||||||
|
|
||||||
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
||||||
GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")"
|
GITHUB_WEB_VERSION="$(curl -s 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null | jq --raw-output .tag_name)"
|
||||||
echo -n " ${GITHUB_WEB_VERSION}" >> "${GITHUB_VERSION_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_WEB_VERSION" "${GITHUB_WEB_VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")"
|
GITHUB_FTL_VERSION="$(curl -s 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null | jq --raw-output .tag_name)"
|
||||||
echo -n " ${GITHUB_FTL_VERSION}" >> "${GITHUB_VERSION_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_FTL_VERSION" "${GITHUB_FTL_VERSION}"
|
||||||
|
|
||||||
|
if [[ "${DOCKER_TAG}" ]]; then
|
||||||
|
GITHUB_DOCKER_VERSION="$(curl -s 'https://api.github.com/repos/pi-hole/docker-pi-hole/releases/latest' 2> /dev/null | jq --raw-output .tag_name)"
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_DOCKER_VERSION" "${GITHUB_DOCKER_VERSION}"
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
LOCAL_BRANCH_FILE="/etc/pihole/localbranches"
|
|
||||||
|
|
||||||
CORE_BRANCH="$(get_local_branch /etc/.pihole)"
|
CORE_BRANCH="$(get_local_branch /etc/.pihole)"
|
||||||
echo -n "${CORE_BRANCH}" > "${LOCAL_BRANCH_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "CORE_BRANCH" "${CORE_BRANCH}"
|
||||||
chmod 644 "${LOCAL_BRANCH_FILE}"
|
|
||||||
|
|
||||||
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
||||||
WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
|
WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
|
||||||
echo -n " ${WEB_BRANCH}" >> "${LOCAL_BRANCH_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "WEB_BRANCH" "${WEB_BRANCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FTL_BRANCH="$(pihole-FTL branch)"
|
FTL_BRANCH="$(pihole-FTL branch)"
|
||||||
echo -n " ${FTL_BRANCH}" >> "${LOCAL_BRANCH_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "FTL_BRANCH" "${FTL_BRANCH}"
|
||||||
|
|
||||||
LOCAL_VERSION_FILE="/etc/pihole/localversions"
|
|
||||||
|
|
||||||
CORE_VERSION="$(get_local_version /etc/.pihole)"
|
CORE_VERSION="$(get_local_version /etc/.pihole)"
|
||||||
echo -n "${CORE_VERSION}" > "${LOCAL_VERSION_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "CORE_VERSION" "${CORE_VERSION}"
|
||||||
chmod 644 "${LOCAL_VERSION_FILE}"
|
|
||||||
|
|
||||||
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
|
||||||
WEB_VERSION="$(get_local_version /var/www/html/admin)"
|
WEB_VERSION="$(get_local_version /var/www/html/admin)"
|
||||||
echo -n " ${WEB_VERSION}" >> "${LOCAL_VERSION_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "WEB_VERSION" "${WEB_VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FTL_VERSION="$(pihole-FTL version)"
|
FTL_VERSION="$(pihole-FTL version)"
|
||||||
echo -n " ${FTL_VERSION}" >> "${LOCAL_VERSION_FILE}"
|
addOrEditKeyValPair "${VERSION_FILE}" "FTL_VERSION" "${FTL_VERSION}"
|
||||||
|
|
||||||
|
if [[ "${DOCKER_TAG}" ]]; then
|
||||||
|
addOrEditKeyValPair "${VERSION_FILE}" "DOCKER_VERSION" "${DOCKER_TAG}"
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
137
advanced/Scripts/utils.sh
Executable file
137
advanced/Scripts/utils.sh
Executable file
@@ -0,0 +1,137 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
|
||||||
|
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Script to hold utility functions for use in other scripts
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
# Basic Housekeeping rules
|
||||||
|
# - Functions must be self contained
|
||||||
|
# - Functions should be grouped with other similar functions
|
||||||
|
# - Functions must be documented
|
||||||
|
# - New functions must have a test added for them in test/test_any_utils.py
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Takes Three arguments: file, key, and value.
|
||||||
|
#
|
||||||
|
# Checks the target file for the existence of the key
|
||||||
|
# - If it exists, it changes the value
|
||||||
|
# - If it does not exist, it adds the value
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# addOrEditKeyValPair "/etc/pihole/setupVars.conf" "BLOCKING_ENABLED" "true"
|
||||||
|
#######################
|
||||||
|
addOrEditKeyValPair() {
|
||||||
|
local file="${1}"
|
||||||
|
local key="${2}"
|
||||||
|
local value="${3}"
|
||||||
|
|
||||||
|
if grep -q "^${key}=" "${file}"; then
|
||||||
|
# Key already exists in file, modify the value
|
||||||
|
sed -i "/^${key}=/c\\${key}=${value}" "${file}"
|
||||||
|
else
|
||||||
|
# Key does not already exist, add it and it's value
|
||||||
|
echo "${key}=${value}" >> "${file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Takes two arguments: file, and key.
|
||||||
|
# Adds a key to target file
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# addKey "/etc/dnsmasq.d/01-pihole.conf" "log-queries"
|
||||||
|
#######################
|
||||||
|
addKey(){
|
||||||
|
local file="${1}"
|
||||||
|
local key="${2}"
|
||||||
|
|
||||||
|
if ! grep -q "^${key}" "${file}"; then
|
||||||
|
# Key does not exist, add it.
|
||||||
|
echo "${key}" >> "${file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# Takes two arguments: file, and key.
|
||||||
|
# Deletes a key or key/value pair from target file
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
# removeKey "/etc/pihole/setupVars.conf" "PIHOLE_DNS_1"
|
||||||
|
#######################
|
||||||
|
removeKey() {
|
||||||
|
local file="${1}"
|
||||||
|
local key="${2}"
|
||||||
|
sed -i "/^${key}/d" "${file}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# returns FTL's current telnet API port based on the setting in /etc/pihole-FTL.conf
|
||||||
|
########################
|
||||||
|
getFTLAPIPort(){
|
||||||
|
local FTLCONFFILE="/etc/pihole/pihole-FTL.conf"
|
||||||
|
local DEFAULT_FTL_PORT=4711
|
||||||
|
local ftl_api_port
|
||||||
|
|
||||||
|
if [ -s "$FTLCONFFILE" ]; then
|
||||||
|
# if FTLPORT is not set in pihole-FTL.conf, use the default port
|
||||||
|
ftl_api_port="$({ grep '^FTLPORT=' "${FTLCONFFILE}" || echo "${DEFAULT_FTL_PORT}"; } | cut -d'=' -f2-)"
|
||||||
|
# Exploit prevention: set the port to the default port if there is malicious (non-numeric)
|
||||||
|
# content set in pihole-FTL.conf
|
||||||
|
expr "${ftl_api_port}" : "[^[:digit:]]" > /dev/null && ftl_api_port="${DEFAULT_FTL_PORT}"
|
||||||
|
else
|
||||||
|
# if there is no pihole-FTL.conf, use the default port
|
||||||
|
ftl_api_port="${DEFAULT_FTL_PORT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${ftl_api_port}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# returns path of FTL's PID file
|
||||||
|
#######################
|
||||||
|
getFTLPIDFile() {
|
||||||
|
local FTLCONFFILE="/etc/pihole/pihole-FTL.conf"
|
||||||
|
local DEFAULT_PID_FILE="/run/pihole-FTL.pid"
|
||||||
|
local FTL_PID_FILE
|
||||||
|
|
||||||
|
if [ -s "${FTLCONFFILE}" ]; then
|
||||||
|
# if PIDFILE is not set in pihole-FTL.conf, use the default path
|
||||||
|
FTL_PID_FILE="$({ grep '^PIDFILE=' "${FTLCONFFILE}" || echo "${DEFAULT_PID_FILE}"; } | cut -d'=' -f2-)"
|
||||||
|
else
|
||||||
|
# if there is no pihole-FTL.conf, use the default path
|
||||||
|
FTL_PID_FILE="${DEFAULT_PID_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${FTL_PID_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# returns FTL's PID based on the content of the pihole-FTL.pid file
|
||||||
|
#
|
||||||
|
# Takes one argument: path to pihole-FTL.pid
|
||||||
|
# Example getFTLPID "/run/pihole-FTL.pid"
|
||||||
|
#######################
|
||||||
|
getFTLPID() {
|
||||||
|
local FTL_PID_FILE="${1}"
|
||||||
|
local FTL_PID
|
||||||
|
|
||||||
|
if [ -s "${FTL_PID_FILE}" ]; then
|
||||||
|
# -s: FILE exists and has a size greater than zero
|
||||||
|
FTL_PID="$(cat "${FTL_PID_FILE}")"
|
||||||
|
# Exploit prevention: unset the variable if there is malicious content
|
||||||
|
# Verify that the value read from the file is numeric
|
||||||
|
expr "${FTL_PID}" : "[^[:digit:]]" > /dev/null && unset FTL_PID
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If FTL is not running, or the PID file contains malicious stuff, substitute
|
||||||
|
# negative PID to signal this
|
||||||
|
FTL_PID=${FTL_PID:=-1}
|
||||||
|
echo "${FTL_PID}"
|
||||||
|
}
|
||||||
@@ -89,17 +89,18 @@ getRemoteVersion(){
|
|||||||
local daemon="${1}"
|
local daemon="${1}"
|
||||||
local version
|
local version
|
||||||
local cachedVersions
|
local cachedVersions
|
||||||
local arrCache
|
cachedVersions="/etc/pihole/versions"
|
||||||
cachedVersions="/etc/pihole/GitHubVersions"
|
|
||||||
|
|
||||||
#If the above file exists, then we can read from that. Prevents overuse of GitHub API
|
#If the above file exists, then we can read from that. Prevents overuse of GitHub API
|
||||||
if [[ -f "$cachedVersions" ]]; then
|
if [[ -f "$cachedVersions" ]]; then
|
||||||
IFS=' ' read -r -a arrCache < "$cachedVersions"
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$cachedVersions"
|
||||||
|
|
||||||
case $daemon in
|
case $daemon in
|
||||||
"pi-hole" ) echo "${arrCache[0]}";;
|
"pi-hole" ) echo "${GITHUB_CORE_VERSION}";;
|
||||||
"AdminLTE" ) [[ "${INSTALL_WEB_INTERFACE}" == true ]] && echo "${arrCache[1]}";;
|
"AdminLTE" ) [[ "${INSTALL_WEB_INTERFACE}" == true ]] && echo "${GITHUB_WEB_VERSION}";;
|
||||||
"FTL" ) [[ "${INSTALL_WEB_INTERFACE}" == true ]] && echo "${arrCache[2]}" || echo "${arrCache[1]}";;
|
"FTL" ) echo "${GITHUB_FTL_VERSION}";;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
|
||||||
|
|
||||||
# Pi-hole: A black hole for Internet advertisements
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
@@ -22,10 +24,13 @@ readonly gravityDBfile="/etc/pihole/gravity.db"
|
|||||||
|
|
||||||
# Source install script for ${setupVars}, ${PI_HOLE_BIN_DIR} and valid_ip()
|
# Source install script for ${setupVars}, ${PI_HOLE_BIN_DIR} and valid_ip()
|
||||||
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
# shellcheck disable=SC2034 # used in basic-install
|
# shellcheck disable=SC2034 # used in basic-install to source the script without running it
|
||||||
PH_TEST="true"
|
SKIP_INSTALL="true"
|
||||||
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
|
|
||||||
|
utilsfile="/opt/pihole/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
coltable="/opt/pihole/COL_TABLE"
|
coltable="/opt/pihole/COL_TABLE"
|
||||||
if [[ -f ${coltable} ]]; then
|
if [[ -f ${coltable} ]]; then
|
||||||
source ${coltable}
|
source ${coltable}
|
||||||
@@ -37,58 +42,52 @@ Example: pihole -a -p password
|
|||||||
Set options for the Admin Console
|
Set options for the Admin Console
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-p, password Set Admin Console password
|
-p, password Set Admin Console password
|
||||||
-c, celsius Set Celsius as preferred temperature unit
|
-c, celsius Set Celsius as preferred temperature unit
|
||||||
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
||||||
-k, kelvin Set Kelvin as preferred temperature unit
|
-k, kelvin Set Kelvin as preferred temperature unit
|
||||||
-e, email Set an administrative contact address for the Block Page
|
-h, --help Show this help dialog
|
||||||
-h, --help Show this help dialog
|
-i, interface Specify dnsmasq's interface listening behavior
|
||||||
-i, interface Specify dnsmasq's interface listening behavior
|
-l, privacylevel Set privacy level (0 = lowest, 3 = highest)
|
||||||
-l, privacylevel Set privacy level (0 = lowest, 3 = highest)
|
-t, teleporter Backup configuration as an archive
|
||||||
-t, teleporter Backup configuration as an archive"
|
-t, teleporter myname.tar.gz Backup configuration to archive with name myname.tar.gz as specified"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
add_setting() {
|
add_setting() {
|
||||||
echo "${1}=${2}" >> "${setupVars}"
|
addOrEditKeyValPair "${setupVars}" "${1}" "${2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_setting() {
|
delete_setting() {
|
||||||
sed -i "/^${1}/d" "${setupVars}"
|
removeKey "${setupVars}" "${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
change_setting() {
|
change_setting() {
|
||||||
delete_setting "${1}"
|
addOrEditKeyValPair "${setupVars}" "${1}" "${2}"
|
||||||
add_setting "${1}" "${2}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addFTLsetting() {
|
addFTLsetting() {
|
||||||
echo "${1}=${2}" >> "${FTLconf}"
|
addOrEditKeyValPair "${FTLconf}" "${1}" "${2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteFTLsetting() {
|
deleteFTLsetting() {
|
||||||
sed -i "/^${1}/d" "${FTLconf}"
|
removeKey "${FTLconf}" "${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
changeFTLsetting() {
|
changeFTLsetting() {
|
||||||
deleteFTLsetting "${1}"
|
addOrEditKeyValPair "${FTLconf}" "${1}" "${2}"
|
||||||
addFTLsetting "${1}" "${2}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_dnsmasq_setting() {
|
add_dnsmasq_setting() {
|
||||||
if [[ "${2}" != "" ]]; then
|
addOrEditKeyValPair "${dnsmasqconfig}" "${1}" "${2}"
|
||||||
echo "${1}=${2}" >> "${dnsmasqconfig}"
|
|
||||||
else
|
|
||||||
echo "${1}" >> "${dnsmasqconfig}"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_dnsmasq_setting() {
|
delete_dnsmasq_setting() {
|
||||||
sed -i "/^${1}/d" "${dnsmasqconfig}"
|
removeKey "${dnsmasqconfig}" "${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTemperatureUnit() {
|
SetTemperatureUnit() {
|
||||||
change_setting "TEMPERATUREUNIT" "${unit}"
|
addOrEditKeyValPair "${setupVars}" "TEMPERATUREUNIT" "${unit}"
|
||||||
echo -e " ${TICK} Set temperature unit to ${unit}"
|
echo -e " ${TICK} Set temperature unit to ${unit}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +122,7 @@ SetWebPassword() {
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [ "${PASSWORD}" == "" ]; then
|
if [ "${PASSWORD}" == "" ]; then
|
||||||
change_setting "WEBPASSWORD" ""
|
addOrEditKeyValPair "${setupVars}" "WEBPASSWORD" ""
|
||||||
echo -e " ${TICK} Password Removed"
|
echo -e " ${TICK} Password Removed"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -136,7 +135,7 @@ SetWebPassword() {
|
|||||||
# We do not wrap this in brackets, otherwise BASH will expand any appropriate syntax
|
# We do not wrap this in brackets, otherwise BASH will expand any appropriate syntax
|
||||||
hash=$(HashPassword "$PASSWORD")
|
hash=$(HashPassword "$PASSWORD")
|
||||||
# Save hash to file
|
# Save hash to file
|
||||||
change_setting "WEBPASSWORD" "${hash}"
|
addOrEditKeyValPair "${setupVars}" "WEBPASSWORD" "${hash}"
|
||||||
echo -e " ${TICK} New password set"
|
echo -e " ${TICK} New password set"
|
||||||
else
|
else
|
||||||
echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
|
echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
|
||||||
@@ -147,7 +146,7 @@ SetWebPassword() {
|
|||||||
ProcessDNSSettings() {
|
ProcessDNSSettings() {
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
delete_dnsmasq_setting "server"
|
removeKey "${dnsmasqconfig}" "server"
|
||||||
|
|
||||||
COUNTER=1
|
COUNTER=1
|
||||||
while true ; do
|
while true ; do
|
||||||
@@ -155,34 +154,34 @@ ProcessDNSSettings() {
|
|||||||
if [ -z "${!var}" ]; then
|
if [ -z "${!var}" ]; then
|
||||||
break;
|
break;
|
||||||
fi
|
fi
|
||||||
add_dnsmasq_setting "server" "${!var}"
|
addKey "${dnsmasqconfig}" "server=${!var}"
|
||||||
(( COUNTER++ ))
|
(( COUNTER++ ))
|
||||||
done
|
done
|
||||||
|
|
||||||
# The option LOCAL_DNS_PORT is deprecated
|
# The option LOCAL_DNS_PORT is deprecated
|
||||||
# We apply it once more, and then convert it into the current format
|
# We apply it once more, and then convert it into the current format
|
||||||
if [ -n "${LOCAL_DNS_PORT}" ]; then
|
if [ -n "${LOCAL_DNS_PORT}" ]; then
|
||||||
add_dnsmasq_setting "server" "127.0.0.1#${LOCAL_DNS_PORT}"
|
addOrEditKeyValPair "${dnsmasqconfig}" "server" "127.0.0.1#${LOCAL_DNS_PORT}"
|
||||||
add_setting "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}"
|
addOrEditKeyValPair "${setupVars}" "PIHOLE_DNS_${COUNTER}" "127.0.0.1#${LOCAL_DNS_PORT}"
|
||||||
delete_setting "LOCAL_DNS_PORT"
|
removeKey "${setupVars}" "LOCAL_DNS_PORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
delete_dnsmasq_setting "domain-needed"
|
removeKey "${dnsmasqconfig}" "domain-needed"
|
||||||
delete_dnsmasq_setting "expand-hosts"
|
removeKey "${dnsmasqconfig}" "expand-hosts"
|
||||||
|
|
||||||
if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then
|
if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then
|
||||||
add_dnsmasq_setting "domain-needed"
|
addKey "${dnsmasqconfig}" "domain-needed"
|
||||||
add_dnsmasq_setting "expand-hosts"
|
addKey "${dnsmasqconfig}" "expand-hosts"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
delete_dnsmasq_setting "bogus-priv"
|
removeKey "${dnsmasqconfig}" "bogus-priv"
|
||||||
|
|
||||||
if [[ "${DNS_BOGUS_PRIV}" == true ]]; then
|
if [[ "${DNS_BOGUS_PRIV}" == true ]]; then
|
||||||
add_dnsmasq_setting "bogus-priv"
|
addKey "${dnsmasqconfig}" "bogus-priv"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
delete_dnsmasq_setting "dnssec"
|
removeKey "${dnsmasqconfig}" "dnssec"
|
||||||
delete_dnsmasq_setting "trust-anchor="
|
removeKey "${dnsmasqconfig}" "trust-anchor"
|
||||||
|
|
||||||
if [[ "${DNSSEC}" == true ]]; then
|
if [[ "${DNSSEC}" == true ]]; then
|
||||||
echo "dnssec
|
echo "dnssec
|
||||||
@@ -190,24 +189,24 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
|
|||||||
" >> "${dnsmasqconfig}"
|
" >> "${dnsmasqconfig}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
delete_dnsmasq_setting "host-record"
|
removeKey "${dnsmasqconfig}" "host-record"
|
||||||
|
|
||||||
if [ -n "${HOSTRECORD}" ]; then
|
if [ -n "${HOSTRECORD}" ]; then
|
||||||
add_dnsmasq_setting "host-record" "${HOSTRECORD}"
|
addOrEditKeyValPair "${dnsmasqconfig}" "host-record" "${HOSTRECORD}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Setup interface listening behavior of dnsmasq
|
# Setup interface listening behavior of dnsmasq
|
||||||
delete_dnsmasq_setting "interface"
|
removeKey "${dnsmasqconfig}" "interface"
|
||||||
delete_dnsmasq_setting "local-service"
|
removeKey "${dnsmasqconfig}" "local-service"
|
||||||
delete_dnsmasq_setting "except-interface"
|
removeKey "${dnsmasqconfig}" "except-interface"
|
||||||
delete_dnsmasq_setting "bind-interfaces"
|
removeKey "${dnsmasqconfig}" "bind-interfaces"
|
||||||
|
|
||||||
if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then
|
if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then
|
||||||
# Listen on all interfaces, permit all origins
|
# Listen on all interfaces, permit all origins
|
||||||
add_dnsmasq_setting "except-interface" "nonexisting"
|
addOrEditKeyValPair "${dnsmasqconfig}" "except-interface" "nonexisting"
|
||||||
elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then
|
elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then
|
||||||
# Listen only on all interfaces, but only local subnets
|
# Listen only on all interfaces, but only local subnets
|
||||||
add_dnsmasq_setting "local-service"
|
addKey "${dnsmasqconfig}" "local-service"
|
||||||
else
|
else
|
||||||
# Options "bind" and "single"
|
# Options "bind" and "single"
|
||||||
# Listen only on one interface
|
# Listen only on one interface
|
||||||
@@ -216,30 +215,30 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
|
|||||||
PIHOLE_INTERFACE="eth0"
|
PIHOLE_INTERFACE="eth0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}"
|
addOrEditKeyValPair "${dnsmasqconfig}" "interface" "${PIHOLE_INTERFACE}"
|
||||||
|
|
||||||
if [[ "${DNSMASQ_LISTENING}" == "bind" ]]; then
|
if [[ "${DNSMASQ_LISTENING}" == "bind" ]]; then
|
||||||
# Really bind to interface
|
# Really bind to interface
|
||||||
add_dnsmasq_setting "bind-interfaces"
|
addKey "${dnsmasqconfig}" "bind-interfaces"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then
|
if [[ "${CONDITIONAL_FORWARDING}" == true ]]; then
|
||||||
# Convert legacy "conditional forwarding" to rev-server configuration
|
# Convert legacy "conditional forwarding" to rev-server configuration
|
||||||
# Remove any existing REV_SERVER settings
|
# Remove any existing REV_SERVER settings
|
||||||
delete_setting "REV_SERVER"
|
removeKey "${setupVars}" "REV_SERVER"
|
||||||
delete_setting "REV_SERVER_DOMAIN"
|
removeKey "${setupVars}" "REV_SERVER_DOMAIN"
|
||||||
delete_setting "REV_SERVER_TARGET"
|
removeKey "${setupVars}" "REV_SERVER_TARGET"
|
||||||
delete_setting "REV_SERVER_CIDR"
|
removeKey "${setupVars}" "REV_SERVER_CIDR"
|
||||||
|
|
||||||
REV_SERVER=true
|
REV_SERVER=true
|
||||||
add_setting "REV_SERVER" "true"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER" "true"
|
||||||
|
|
||||||
REV_SERVER_DOMAIN="${CONDITIONAL_FORWARDING_DOMAIN}"
|
REV_SERVER_DOMAIN="${CONDITIONAL_FORWARDING_DOMAIN}"
|
||||||
add_setting "REV_SERVER_DOMAIN" "${REV_SERVER_DOMAIN}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_DOMAIN" "${REV_SERVER_DOMAIN}"
|
||||||
|
|
||||||
REV_SERVER_TARGET="${CONDITIONAL_FORWARDING_IP}"
|
REV_SERVER_TARGET="${CONDITIONAL_FORWARDING_IP}"
|
||||||
add_setting "REV_SERVER_TARGET" "${REV_SERVER_TARGET}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_TARGET" "${REV_SERVER_TARGET}"
|
||||||
|
|
||||||
#Convert CONDITIONAL_FORWARDING_REVERSE if necessary e.g:
|
#Convert CONDITIONAL_FORWARDING_REVERSE if necessary e.g:
|
||||||
# 1.1.168.192.in-addr.arpa to 192.168.1.1/32
|
# 1.1.168.192.in-addr.arpa to 192.168.1.1/32
|
||||||
@@ -266,28 +265,28 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
|
|||||||
# shellcheck disable=2001
|
# shellcheck disable=2001
|
||||||
REV_SERVER_CIDR="$(sed "s+\\.[0-9]*$+\\.0/24+" <<< "${REV_SERVER_TARGET}")"
|
REV_SERVER_CIDR="$(sed "s+\\.[0-9]*$+\\.0/24+" <<< "${REV_SERVER_TARGET}")"
|
||||||
fi
|
fi
|
||||||
add_setting "REV_SERVER_CIDR" "${REV_SERVER_CIDR}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_CIDR" "${REV_SERVER_CIDR}"
|
||||||
|
|
||||||
# Remove obsolete settings from setupVars.conf
|
# Remove obsolete settings from setupVars.conf
|
||||||
delete_setting "CONDITIONAL_FORWARDING"
|
removeKey "${setupVars}" "CONDITIONAL_FORWARDING"
|
||||||
delete_setting "CONDITIONAL_FORWARDING_REVERSE"
|
removeKey "${setupVars}" "CONDITIONAL_FORWARDING_REVERSE"
|
||||||
delete_setting "CONDITIONAL_FORWARDING_DOMAIN"
|
removeKey "${setupVars}" "CONDITIONAL_FORWARDING_DOMAIN"
|
||||||
delete_setting "CONDITIONAL_FORWARDING_IP"
|
removeKey "${setupVars}" "CONDITIONAL_FORWARDING_IP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
delete_dnsmasq_setting "rev-server"
|
removeKey "${dnsmasqconfig}" "rev-server"
|
||||||
|
|
||||||
if [[ "${REV_SERVER}" == true ]]; then
|
if [[ "${REV_SERVER}" == true ]]; then
|
||||||
add_dnsmasq_setting "rev-server=${REV_SERVER_CIDR},${REV_SERVER_TARGET}"
|
addKey "${dnsmasqconfig}" "rev-server=${REV_SERVER_CIDR},${REV_SERVER_TARGET}"
|
||||||
if [ -n "${REV_SERVER_DOMAIN}" ]; then
|
if [ -n "${REV_SERVER_DOMAIN}" ]; then
|
||||||
# Forward local domain names to the CF target, too
|
# Forward local domain names to the CF target, too
|
||||||
add_dnsmasq_setting "server=/${REV_SERVER_DOMAIN}/${REV_SERVER_TARGET}"
|
addKey "${dnsmasqconfig}" "server=/${REV_SERVER_DOMAIN}/${REV_SERVER_TARGET}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${DNS_FQDN_REQUIRED}" != true ]]; then
|
if [[ "${DNS_FQDN_REQUIRED}" != true ]]; then
|
||||||
# Forward unqualified names to the CF target only when the "never
|
# Forward unqualified names to the CF target only when the "never
|
||||||
# forward non-FQDN" option is unticked
|
# forward non-FQDN" option is unticked
|
||||||
add_dnsmasq_setting "server=//${REV_SERVER_TARGET}"
|
addKey "${dnsmasqconfig}" "server=//${REV_SERVER_TARGET}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
@@ -296,13 +295,13 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423
|
|||||||
# changes in the non-FQDN forwarding. This cannot be done in 01-pihole.conf
|
# changes in the non-FQDN forwarding. This cannot be done in 01-pihole.conf
|
||||||
# as we don't want to delete all local=/.../ lines so it's much safer to
|
# as we don't want to delete all local=/.../ lines so it's much safer to
|
||||||
# simply rewrite the entire corresponding config file (which is what the
|
# simply rewrite the entire corresponding config file (which is what the
|
||||||
# DHCP settings subroutie is doing)
|
# DHCP settings subroutine is doing)
|
||||||
ProcessDHCPSettings
|
ProcessDHCPSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDNSServers() {
|
SetDNSServers() {
|
||||||
# Save setting to file
|
# Save setting to file
|
||||||
delete_setting "PIHOLE_DNS"
|
removeKey "${setupVars}" "PIHOLE_DNS"
|
||||||
IFS=',' read -r -a array <<< "${args[2]}"
|
IFS=',' read -r -a array <<< "${args[2]}"
|
||||||
for index in "${!array[@]}"
|
for index in "${!array[@]}"
|
||||||
do
|
do
|
||||||
@@ -311,7 +310,7 @@ SetDNSServers() {
|
|||||||
ip="${array[index]//\\#/#}"
|
ip="${array[index]//\\#/#}"
|
||||||
|
|
||||||
if valid_ip "${ip}" || valid_ip6 "${ip}" ; then
|
if valid_ip "${ip}" || valid_ip6 "${ip}" ; then
|
||||||
add_setting "PIHOLE_DNS_$((index+1))" "${ip}"
|
addOrEditKeyValPair "${setupVars}" "PIHOLE_DNS_$((index+1))" "${ip}"
|
||||||
else
|
else
|
||||||
echo -e " ${CROSS} Invalid IP has been passed"
|
echo -e " ${CROSS} Invalid IP has been passed"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -319,30 +318,30 @@ SetDNSServers() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "${args[3]}" == "domain-needed" ]]; then
|
if [[ "${args[3]}" == "domain-needed" ]]; then
|
||||||
change_setting "DNS_FQDN_REQUIRED" "true"
|
addOrEditKeyValPair "${setupVars}" "DNS_FQDN_REQUIRED" "true"
|
||||||
else
|
else
|
||||||
change_setting "DNS_FQDN_REQUIRED" "false"
|
addOrEditKeyValPair "${setupVars}" "DNS_FQDN_REQUIRED" "false"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${args[4]}" == "bogus-priv" ]]; then
|
if [[ "${args[4]}" == "bogus-priv" ]]; then
|
||||||
change_setting "DNS_BOGUS_PRIV" "true"
|
addOrEditKeyValPair "${setupVars}" "DNS_BOGUS_PRIV" "true"
|
||||||
else
|
else
|
||||||
change_setting "DNS_BOGUS_PRIV" "false"
|
addOrEditKeyValPair "${setupVars}" "DNS_BOGUS_PRIV" "false"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${args[5]}" == "dnssec" ]]; then
|
if [[ "${args[5]}" == "dnssec" ]]; then
|
||||||
change_setting "DNSSEC" "true"
|
addOrEditKeyValPair "${setupVars}" "DNSSEC" "true"
|
||||||
else
|
else
|
||||||
change_setting "DNSSEC" "false"
|
addOrEditKeyValPair "${setupVars}" "DNSSEC" "false"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${args[6]}" == "rev-server" ]]; then
|
if [[ "${args[6]}" == "rev-server" ]]; then
|
||||||
change_setting "REV_SERVER" "true"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER" "true"
|
||||||
change_setting "REV_SERVER_CIDR" "${args[7]}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_CIDR" "${args[7]}"
|
||||||
change_setting "REV_SERVER_TARGET" "${args[8]}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_TARGET" "${args[8]}"
|
||||||
change_setting "REV_SERVER_DOMAIN" "${args[9]}"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER_DOMAIN" "${args[9]}"
|
||||||
else
|
else
|
||||||
change_setting "REV_SERVER" "false"
|
addOrEditKeyValPair "${setupVars}" "REV_SERVER" "false"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ProcessDNSSettings
|
ProcessDNSSettings
|
||||||
@@ -352,11 +351,11 @@ SetDNSServers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetExcludeDomains() {
|
SetExcludeDomains() {
|
||||||
change_setting "API_EXCLUDE_DOMAINS" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "API_EXCLUDE_DOMAINS" "${args[2]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
SetExcludeClients() {
|
SetExcludeClients() {
|
||||||
change_setting "API_EXCLUDE_CLIENTS" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "API_EXCLUDE_CLIENTS" "${args[2]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
Poweroff(){
|
Poweroff(){
|
||||||
@@ -372,7 +371,7 @@ RestartDNS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetQueryLogOptions() {
|
SetQueryLogOptions() {
|
||||||
change_setting "API_QUERY_LOG_SHOW" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "API_QUERY_LOG_SHOW" "${args[2]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessDHCPSettings() {
|
ProcessDHCPSettings() {
|
||||||
@@ -388,19 +387,14 @@ ProcessDHCPSettings() {
|
|||||||
|
|
||||||
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
|
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
|
||||||
PIHOLE_DOMAIN="lan"
|
PIHOLE_DOMAIN="lan"
|
||||||
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
|
addOrEditKeyValPair "${setupVars}" "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${DHCP_LEASETIME}" == "0" ]]; then
|
if [[ "${DHCP_LEASETIME}" == "0" ]]; then
|
||||||
leasetime="infinite"
|
leasetime="infinite"
|
||||||
elif [[ "${DHCP_LEASETIME}" == "" ]]; then
|
elif [[ "${DHCP_LEASETIME}" == "" ]]; then
|
||||||
leasetime="24"
|
leasetime="24h"
|
||||||
change_setting "DHCP_LEASETIME" "${leasetime}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_LEASETIME" "24"
|
||||||
elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then
|
|
||||||
#Installation is affected by known bug, introduced in a previous version.
|
|
||||||
#This will automatically clean up setupVars.conf and remove the unnecessary "h"
|
|
||||||
leasetime="24"
|
|
||||||
change_setting "DHCP_LEASETIME" "${leasetime}"
|
|
||||||
else
|
else
|
||||||
leasetime="${DHCP_LEASETIME}h"
|
leasetime="${DHCP_LEASETIME}h"
|
||||||
fi
|
fi
|
||||||
@@ -440,8 +434,8 @@ dhcp-leasefile=/etc/pihole/dhcp.leases
|
|||||||
echo "#quiet-dhcp6
|
echo "#quiet-dhcp6
|
||||||
#enable-ra
|
#enable-ra
|
||||||
dhcp-option=option6:dns-server,[::]
|
dhcp-option=option6:dns-server,[::]
|
||||||
dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,64,3600
|
dhcp-range=::,constructor:${interface},ra-names,ra-stateless,64
|
||||||
ra-param=*,0,0
|
|
||||||
" >> "${dhcpconfig}"
|
" >> "${dhcpconfig}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -453,24 +447,24 @@ ra-param=*,0,0
|
|||||||
}
|
}
|
||||||
|
|
||||||
EnableDHCP() {
|
EnableDHCP() {
|
||||||
change_setting "DHCP_ACTIVE" "true"
|
addOrEditKeyValPair "${setupVars}" "DHCP_ACTIVE" "true"
|
||||||
change_setting "DHCP_START" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_START" "${args[2]}"
|
||||||
change_setting "DHCP_END" "${args[3]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_END" "${args[3]}"
|
||||||
change_setting "DHCP_ROUTER" "${args[4]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_ROUTER" "${args[4]}"
|
||||||
change_setting "DHCP_LEASETIME" "${args[5]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_LEASETIME" "${args[5]}"
|
||||||
change_setting "PIHOLE_DOMAIN" "${args[6]}"
|
addOrEditKeyValPair "${setupVars}" "PIHOLE_DOMAIN" "${args[6]}"
|
||||||
change_setting "DHCP_IPv6" "${args[7]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_IPv6" "${args[7]}"
|
||||||
change_setting "DHCP_rapid_commit" "${args[8]}"
|
addOrEditKeyValPair "${setupVars}" "DHCP_rapid_commit" "${args[8]}"
|
||||||
|
|
||||||
# Remove possible old setting from file
|
# Remove possible old setting from file
|
||||||
delete_dnsmasq_setting "dhcp-"
|
removeKey "${dnsmasqconfig}" "dhcp-"
|
||||||
delete_dnsmasq_setting "quiet-dhcp"
|
removeKey "${dnsmasqconfig}" "quiet-dhcp"
|
||||||
|
|
||||||
# If a DHCP client claims that its name is "wpad", ignore that.
|
# If a DHCP client claims that its name is "wpad", ignore that.
|
||||||
# This fixes a security hole. see CERT Vulnerability VU#598349
|
# This fixes a security hole. see CERT Vulnerability VU#598349
|
||||||
# We also ignore "localhost" as Windows behaves strangely if a
|
# We also ignore "localhost" as Windows behaves strangely if a
|
||||||
# device claims this host name
|
# device claims this host name
|
||||||
add_dnsmasq_setting "dhcp-name-match=set:hostname-ignore,wpad
|
addKey "${dnsmasqconfig}" "dhcp-name-match=set:hostname-ignore,wpad
|
||||||
dhcp-name-match=set:hostname-ignore,localhost
|
dhcp-name-match=set:hostname-ignore,localhost
|
||||||
dhcp-ignore-names=tag:hostname-ignore"
|
dhcp-ignore-names=tag:hostname-ignore"
|
||||||
|
|
||||||
@@ -480,11 +474,11 @@ dhcp-ignore-names=tag:hostname-ignore"
|
|||||||
}
|
}
|
||||||
|
|
||||||
DisableDHCP() {
|
DisableDHCP() {
|
||||||
change_setting "DHCP_ACTIVE" "false"
|
addOrEditKeyValPair "${setupVars}" "DHCP_ACTIVE" "false"
|
||||||
|
|
||||||
# Remove possible old setting from file
|
# Remove possible old setting from file
|
||||||
delete_dnsmasq_setting "dhcp-"
|
removeKey "${dnsmasqconfig}" "dhcp-"
|
||||||
delete_dnsmasq_setting "quiet-dhcp"
|
removeKey "${dnsmasqconfig}" "quiet-dhcp"
|
||||||
|
|
||||||
ProcessDHCPSettings
|
ProcessDHCPSettings
|
||||||
|
|
||||||
@@ -492,11 +486,11 @@ DisableDHCP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetWebUILayout() {
|
SetWebUILayout() {
|
||||||
change_setting "WEBUIBOXEDLAYOUT" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "WEBUIBOXEDLAYOUT" "${args[2]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWebUITheme() {
|
SetWebUITheme() {
|
||||||
change_setting "WEBTHEME" "${args[2]}"
|
addOrEditKeyValPair "${setupVars}" "WEBTHEME" "${args[2]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckUrl(){
|
CheckUrl(){
|
||||||
@@ -523,13 +517,13 @@ CustomizeAdLists() {
|
|||||||
|
|
||||||
if CheckUrl "${address}"; then
|
if CheckUrl "${address}"; then
|
||||||
if [[ "${args[2]}" == "enable" ]]; then
|
if [[ "${args[2]}" == "enable" ]]; then
|
||||||
sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 1 WHERE address = '${address}'"
|
pihole-FTL sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 1 WHERE address = '${address}'"
|
||||||
elif [[ "${args[2]}" == "disable" ]]; then
|
elif [[ "${args[2]}" == "disable" ]]; then
|
||||||
sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 0 WHERE address = '${address}'"
|
pihole-FTL sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 0 WHERE address = '${address}'"
|
||||||
elif [[ "${args[2]}" == "add" ]]; then
|
elif [[ "${args[2]}" == "add" ]]; then
|
||||||
sqlite3 "${gravityDBfile}" "INSERT OR IGNORE INTO adlist (address, comment) VALUES ('${address}', '${comment}')"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT OR IGNORE INTO adlist (address, comment) VALUES ('${address}', '${comment}')"
|
||||||
elif [[ "${args[2]}" == "del" ]]; then
|
elif [[ "${args[2]}" == "del" ]]; then
|
||||||
sqlite3 "${gravityDBfile}" "DELETE FROM adlist WHERE address = '${address}'"
|
pihole-FTL sqlite3 "${gravityDBfile}" "DELETE FROM adlist WHERE address = '${address}'"
|
||||||
else
|
else
|
||||||
echo "Not permitted"
|
echo "Not permitted"
|
||||||
return 1
|
return 1
|
||||||
@@ -568,37 +562,6 @@ RemoveDHCPStaticAddress() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetAdminEmail() {
|
|
||||||
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
|
|
||||||
echo "Usage: pihole -a email <address>
|
|
||||||
Example: 'pihole -a email admin@address.com'
|
|
||||||
Set an administrative contact address for the Block Page
|
|
||||||
|
|
||||||
Options:
|
|
||||||
\"\" Empty: Remove admin contact
|
|
||||||
-h, --help Show this help dialog"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "${args[2]}" ]]; then
|
|
||||||
|
|
||||||
# Sanitize email address in case of security issues
|
|
||||||
# Regex from https://stackoverflow.com/a/2138832/4065967
|
|
||||||
local regex
|
|
||||||
regex="^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\$"
|
|
||||||
if [[ ! "${args[2]}" =~ ${regex} ]]; then
|
|
||||||
echo -e " ${CROSS} Invalid email address"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
change_setting "ADMIN_EMAIL" "${args[2]}"
|
|
||||||
echo -e " ${TICK} Setting admin contact to ${args[2]}"
|
|
||||||
else
|
|
||||||
change_setting "ADMIN_EMAIL" ""
|
|
||||||
echo -e " ${TICK} Removing admin contact"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
SetListeningMode() {
|
SetListeningMode() {
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
|
|
||||||
@@ -618,16 +581,16 @@ Interfaces:
|
|||||||
|
|
||||||
if [[ "${args[2]}" == "all" ]]; then
|
if [[ "${args[2]}" == "all" ]]; then
|
||||||
echo -e " ${INFO} Listening on all interfaces, permitting all origins. Please use a firewall!"
|
echo -e " ${INFO} Listening on all interfaces, permitting all origins. Please use a firewall!"
|
||||||
change_setting "DNSMASQ_LISTENING" "all"
|
addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "all"
|
||||||
elif [[ "${args[2]}" == "local" ]]; then
|
elif [[ "${args[2]}" == "local" ]]; then
|
||||||
echo -e " ${INFO} Listening on all interfaces, permitting origins from one hop away (LAN)"
|
echo -e " ${INFO} Listening on all interfaces, permitting origins from one hop away (LAN)"
|
||||||
change_setting "DNSMASQ_LISTENING" "local"
|
addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "local"
|
||||||
elif [[ "${args[2]}" == "bind" ]]; then
|
elif [[ "${args[2]}" == "bind" ]]; then
|
||||||
echo -e " ${INFO} Binding on interface ${PIHOLE_INTERFACE}"
|
echo -e " ${INFO} Binding on interface ${PIHOLE_INTERFACE}"
|
||||||
change_setting "DNSMASQ_LISTENING" "bind"
|
addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "bind"
|
||||||
else
|
else
|
||||||
echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}"
|
echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}"
|
||||||
change_setting "DNSMASQ_LISTENING" "single"
|
addOrEditKeyValPair "${setupVars}" "DNSMASQ_LISTENING" "single"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Don't restart DNS server yet because other settings
|
# Don't restart DNS server yet because other settings
|
||||||
@@ -640,12 +603,18 @@ Interfaces:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Teleporter() {
|
Teleporter() {
|
||||||
local datetimestamp
|
local filename
|
||||||
local host
|
filename="${args[2]}"
|
||||||
datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S")
|
if [[ -z "${filename}" ]]; then
|
||||||
host=$(hostname)
|
local datetimestamp
|
||||||
host="${host//./_}"
|
local host
|
||||||
php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-${host:-noname}-teleporter_${datetimestamp}.tar.gz"
|
datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S")
|
||||||
|
host=$(hostname)
|
||||||
|
host="${host//./_}"
|
||||||
|
filename="pi-hole-${host:-noname}-teleporter_${datetimestamp}.tar.gz"
|
||||||
|
fi
|
||||||
|
# webroot is sourced from basic-install above
|
||||||
|
php "${webroot}/admin/scripts/pi-hole/php/teleporter.php" > "${filename}"
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDomain()
|
checkDomain()
|
||||||
@@ -681,18 +650,18 @@ addAudit()
|
|||||||
done
|
done
|
||||||
# Insert only the domain here. The date_added field will be
|
# Insert only the domain here. The date_added field will be
|
||||||
# filled with its default value (date_added = current timestamp)
|
# filled with its default value (date_added = current timestamp)
|
||||||
sqlite3 "${gravityDBfile}" "INSERT INTO domain_audit (domain) VALUES ${domains};"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT INTO domain_audit (domain) VALUES ${domains};"
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAudit()
|
clearAudit()
|
||||||
{
|
{
|
||||||
sqlite3 "${gravityDBfile}" "DELETE FROM domain_audit;"
|
pihole-FTL sqlite3 "${gravityDBfile}" "DELETE FROM domain_audit;"
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPrivacyLevel() {
|
SetPrivacyLevel() {
|
||||||
# Set privacy level. Minimum is 0, maximum is 3
|
# Set privacy level. Minimum is 0, maximum is 3
|
||||||
if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then
|
if [ "${args[2]}" -ge 0 ] && [ "${args[2]}" -le 3 ]; then
|
||||||
changeFTLsetting "PRIVACYLEVEL" "${args[2]}"
|
addOrEditKeyValPair "${FTLconf}" "PRIVACYLEVEL" "${args[2]}"
|
||||||
pihole restartdns reload-lists
|
pihole restartdns reload-lists
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -733,7 +702,7 @@ RemoveCustomDNSAddress() {
|
|||||||
validHost="$(checkDomain "${host}")"
|
validHost="$(checkDomain "${host}")"
|
||||||
if [[ -n "${validHost}" ]]; then
|
if [[ -n "${validHost}" ]]; then
|
||||||
if valid_ip "${ip}" || valid_ip6 "${ip}" ; then
|
if valid_ip "${ip}" || valid_ip6 "${ip}" ; then
|
||||||
sed -i "/^${ip} ${validHost}$/d" "${dnscustomfile}"
|
sed -i "/^${ip} ${validHost}$/Id" "${dnscustomfile}"
|
||||||
else
|
else
|
||||||
echo -e " ${CROSS} Invalid IP has been passed"
|
echo -e " ${CROSS} Invalid IP has been passed"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -786,7 +755,7 @@ RemoveCustomCNAMERecord() {
|
|||||||
if [[ -n "${validDomain}" ]]; then
|
if [[ -n "${validDomain}" ]]; then
|
||||||
validTarget="$(checkDomain "${target}")"
|
validTarget="$(checkDomain "${target}")"
|
||||||
if [[ -n "${validTarget}" ]]; then
|
if [[ -n "${validTarget}" ]]; then
|
||||||
sed -i "/cname=${validDomain},${validTarget}$/d" "${dnscustomcnamefile}"
|
sed -i "/cname=${validDomain},${validTarget}$/Id" "${dnscustomcnamefile}"
|
||||||
else
|
else
|
||||||
echo " ${CROSS} Invalid Target Passed!"
|
echo " ${CROSS} Invalid Target Passed!"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -802,6 +771,23 @@ RemoveCustomCNAMERecord() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetRateLimit() {
|
||||||
|
local rate_limit_count rate_limit_interval reload
|
||||||
|
rate_limit_count="${args[2]}"
|
||||||
|
rate_limit_interval="${args[3]}"
|
||||||
|
reload="${args[4]}"
|
||||||
|
|
||||||
|
# Set rate-limit setting inf valid
|
||||||
|
if [ "${rate_limit_count}" -ge 0 ] && [ "${rate_limit_interval}" -ge 0 ]; then
|
||||||
|
addOrEditKeyValPair "${FTLconf}" "RATE_LIMIT" "${rate_limit_count}/${rate_limit_interval}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restart FTL to update rate-limit settings only if $reload not false
|
||||||
|
if [[ ! $reload == "false" ]]; then
|
||||||
|
RestartDNS
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
args=("$@")
|
args=("$@")
|
||||||
|
|
||||||
@@ -824,7 +810,6 @@ main() {
|
|||||||
"-h" | "--help" ) helpFunc;;
|
"-h" | "--help" ) helpFunc;;
|
||||||
"addstaticdhcp" ) AddDHCPStaticAddress;;
|
"addstaticdhcp" ) AddDHCPStaticAddress;;
|
||||||
"removestaticdhcp" ) RemoveDHCPStaticAddress;;
|
"removestaticdhcp" ) RemoveDHCPStaticAddress;;
|
||||||
"-e" | "email" ) SetAdminEmail "$3";;
|
|
||||||
"-i" | "interface" ) SetListeningMode "$@";;
|
"-i" | "interface" ) SetListeningMode "$@";;
|
||||||
"-t" | "teleporter" ) Teleporter;;
|
"-t" | "teleporter" ) Teleporter;;
|
||||||
"adlist" ) CustomizeAdLists;;
|
"adlist" ) CustomizeAdLists;;
|
||||||
@@ -835,6 +820,7 @@ main() {
|
|||||||
"removecustomdns" ) RemoveCustomDNSAddress;;
|
"removecustomdns" ) RemoveCustomDNSAddress;;
|
||||||
"addcustomcname" ) AddCustomCNAMERecord;;
|
"addcustomcname" ) AddCustomCNAMERecord;;
|
||||||
"removecustomcname" ) RemoveCustomCNAMERecord;;
|
"removecustomcname" ) RemoveCustomCNAMERecord;;
|
||||||
|
"ratelimit" ) SetRateLimit;;
|
||||||
* ) helpFunc;;
|
* ) helpFunc;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,17 @@ INSERT OR REPLACE INTO "group" SELECT * FROM OLD."group";
|
|||||||
INSERT OR REPLACE INTO domain_audit SELECT * FROM OLD.domain_audit;
|
INSERT OR REPLACE INTO domain_audit SELECT * FROM OLD.domain_audit;
|
||||||
|
|
||||||
INSERT OR REPLACE INTO domainlist SELECT * FROM OLD.domainlist;
|
INSERT OR REPLACE INTO domainlist SELECT * FROM OLD.domainlist;
|
||||||
|
DELETE FROM OLD.domainlist_by_group WHERE domainlist_id NOT IN (SELECT id FROM OLD.domainlist);
|
||||||
INSERT OR REPLACE INTO domainlist_by_group SELECT * FROM OLD.domainlist_by_group;
|
INSERT OR REPLACE INTO domainlist_by_group SELECT * FROM OLD.domainlist_by_group;
|
||||||
|
|
||||||
INSERT OR REPLACE INTO adlist SELECT * FROM OLD.adlist;
|
INSERT OR REPLACE INTO adlist SELECT * FROM OLD.adlist;
|
||||||
|
DELETE FROM OLD.adlist_by_group WHERE adlist_id NOT IN (SELECT id FROM OLD.adlist);
|
||||||
INSERT OR REPLACE INTO adlist_by_group SELECT * FROM OLD.adlist_by_group;
|
INSERT OR REPLACE INTO adlist_by_group SELECT * FROM OLD.adlist_by_group;
|
||||||
|
|
||||||
INSERT OR REPLACE INTO info SELECT * FROM OLD.info;
|
INSERT OR REPLACE INTO info SELECT * FROM OLD.info;
|
||||||
|
|
||||||
INSERT OR REPLACE INTO client SELECT * FROM OLD.client;
|
INSERT OR REPLACE INTO client SELECT * FROM OLD.client;
|
||||||
|
DELETE FROM OLD.client_by_group WHERE client_id NOT IN (SELECT id FROM OLD.client);
|
||||||
INSERT OR REPLACE INTO client_by_group SELECT * FROM OLD.client_by_group;
|
INSERT OR REPLACE INTO client_by_group SELECT * FROM OLD.client_by_group;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/var/log/pihole.log {
|
/var/log/pihole/pihole.log {
|
||||||
# su #
|
# su #
|
||||||
daily
|
daily
|
||||||
copytruncate
|
copytruncate
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
nomail
|
nomail
|
||||||
}
|
}
|
||||||
|
|
||||||
/var/log/pihole-FTL.log {
|
/var/log/pihole/FTL.log {
|
||||||
# su #
|
# su #
|
||||||
weekly
|
weekly
|
||||||
copytruncate
|
copytruncate
|
||||||
|
|||||||
@@ -9,8 +9,17 @@
|
|||||||
# Description: Enable service provided by pihole-FTL daemon
|
# Description: Enable service provided by pihole-FTL daemon
|
||||||
### END INIT INFO
|
### END INIT INFO
|
||||||
|
|
||||||
|
#source utils.sh for getFTLPIDFile(), getFTLPID ()
|
||||||
|
PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
. "${utilsfile}"
|
||||||
|
|
||||||
|
|
||||||
is_running() {
|
is_running() {
|
||||||
pgrep -xo "pihole-FTL" > /dev/null
|
if [ -d "/proc/${FTL_PID}" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -20,22 +29,38 @@ start() {
|
|||||||
echo "pihole-FTL is already running"
|
echo "pihole-FTL is already running"
|
||||||
else
|
else
|
||||||
# Touch files to ensure they exist (create if non-existing, preserve if existing)
|
# Touch files to ensure they exist (create if non-existing, preserve if existing)
|
||||||
mkdir -pm 0755 /run/pihole
|
mkdir -pm 0755 /run/pihole /var/log/pihole
|
||||||
touch /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole-FTL.log /var/log/pihole.log /etc/pihole/dhcp.leases
|
[ ! -f "${FTL_PID_FILE}" ] && install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}"
|
||||||
|
[ ! -f /var/log/pihole/FTL.log ] && install -m 644 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log
|
||||||
|
[ ! -f /var/log/pihole/pihole.log ] && install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log
|
||||||
|
[ ! -f /etc/pihole/dhcp.leases ] && install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases
|
||||||
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
|
# Ensure that permissions are set so that pihole-FTL can edit all necessary files
|
||||||
chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole-FTL.log /var/log/pihole.log /etc/pihole/dhcp.leases /run/pihole /etc/pihole
|
chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases
|
||||||
chmod 0644 /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole-FTL.log /var/log/pihole.log /etc/pihole/dhcp.leases
|
|
||||||
# Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist
|
# Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist
|
||||||
chmod -f 0644 /etc/pihole/macvendor.db
|
chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log
|
||||||
|
chmod -f 0640 /var/log/pihole/pihole.log
|
||||||
# Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist
|
# Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist
|
||||||
chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db
|
chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db
|
||||||
# Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist
|
# Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist
|
||||||
chmod -f 0664 /etc/pihole/pihole-FTL.db
|
chmod -f 0664 /etc/pihole/pihole-FTL.db
|
||||||
|
|
||||||
|
# Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole/
|
||||||
|
# Should be removed with Pi-hole v6.0
|
||||||
|
if [ ! -f /var/log/pihole.log ]; then
|
||||||
|
ln -s /var/log/pihole/pihole.log /var/log/pihole.log
|
||||||
|
chown -h pihole:pihole /var/log/pihole.log
|
||||||
|
|
||||||
|
fi
|
||||||
|
if [ ! -f /var/log/pihole-FTL.log ]; then
|
||||||
|
ln -s /var/log/pihole/FTL.log /var/log/pihole-FTL.log
|
||||||
|
chown -h pihole:pihole /var/log/pihole-FTL.log
|
||||||
|
fi
|
||||||
|
|
||||||
if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then
|
if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then
|
||||||
su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole
|
su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole || exit $?
|
||||||
else
|
else
|
||||||
echo "Warning: Starting pihole-FTL as root because setting capabilities is not supported on this system"
|
echo "Warning: Starting pihole-FTL as root because setting capabilities is not supported on this system"
|
||||||
/usr/bin/pihole-FTL
|
/usr/bin/pihole-FTL || exit $?
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
@@ -44,7 +69,7 @@ start() {
|
|||||||
# Stop the service
|
# Stop the service
|
||||||
stop() {
|
stop() {
|
||||||
if is_running; then
|
if is_running; then
|
||||||
pkill -xo "pihole-FTL"
|
kill "${FTL_PID}"
|
||||||
for i in 1 2 3 4 5; do
|
for i in 1 2 3 4 5; do
|
||||||
if ! is_running; then
|
if ! is_running; then
|
||||||
break
|
break
|
||||||
@@ -57,8 +82,7 @@ stop() {
|
|||||||
|
|
||||||
if is_running; then
|
if is_running; then
|
||||||
echo "Not stopped; may still be shutting down or shutdown may have failed, killing now"
|
echo "Not stopped; may still be shutting down or shutdown may have failed, killing now"
|
||||||
pkill -xo -9 "pihole-FTL"
|
kill -9 "${FTL_PID}"
|
||||||
exit 1
|
|
||||||
else
|
else
|
||||||
echo "Stopped"
|
echo "Stopped"
|
||||||
fi
|
fi
|
||||||
@@ -66,7 +90,7 @@ stop() {
|
|||||||
echo "Not running"
|
echo "Not running"
|
||||||
fi
|
fi
|
||||||
# Cleanup
|
# Cleanup
|
||||||
rm -f /run/pihole/FTL.sock /dev/shm/FTL-*
|
rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}"
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +107,13 @@ status() {
|
|||||||
|
|
||||||
|
|
||||||
### main logic ###
|
### main logic ###
|
||||||
|
|
||||||
|
# Get file paths
|
||||||
|
FTL_PID_FILE="$(getFTLPIDFile)"
|
||||||
|
|
||||||
|
# Get FTL's current PID
|
||||||
|
FTL_PID="$(getFTLPID ${FTL_PID_FILE})"
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
stop)
|
stop)
|
||||||
stop
|
stop
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
# early morning. Download any updates from the adlists
|
# early morning. Download any updates from the adlists
|
||||||
# Squash output to log, then splat the log to stdout on error to allow for
|
# Squash output to log, then splat the log to stdout on error to allow for
|
||||||
# standard crontab job error handling.
|
# standard crontab job error handling.
|
||||||
59 1 * * 7 root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole_updateGravity.log || cat /var/log/pihole_updateGravity.log
|
59 1 * * 7 root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole/pihole_updateGravity.log || cat /var/log/pihole/pihole_updateGravity.log
|
||||||
|
|
||||||
# Pi-hole: Flush the log daily at 00:00
|
# Pi-hole: Flush the log daily at 00:00
|
||||||
# The flush script will use logrotate if available
|
# The flush script will use logrotate if available
|
||||||
@@ -28,9 +28,6 @@
|
|||||||
|
|
||||||
@reboot root /usr/sbin/logrotate --state /var/lib/logrotate/pihole /etc/pihole/logrotate
|
@reboot root /usr/sbin/logrotate --state /var/lib/logrotate/pihole /etc/pihole/logrotate
|
||||||
|
|
||||||
# Pi-hole: Grab local version and branch every 10 minutes
|
|
||||||
*/10 * * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker local
|
|
||||||
|
|
||||||
# Pi-hole: Grab remote version every 24 hours
|
# Pi-hole: Grab remote version every 24 hours
|
||||||
59 17 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker remote
|
59 17 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker remote
|
||||||
@reboot root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker remote reboot
|
@reboot root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updatechecker remote reboot
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ _pihole() {
|
|||||||
COMPREPLY=( $(compgen -W "${opts_lists}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${opts_lists}" -- ${cur}) )
|
||||||
;;
|
;;
|
||||||
"admin")
|
"admin")
|
||||||
opts_admin="celsius email fahrenheit interface kelvin password privacylevel"
|
opts_admin="celsius fahrenheit interface kelvin password privacylevel"
|
||||||
COMPREPLY=( $(compgen -W "${opts_admin}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${opts_admin}" -- ${cur}) )
|
||||||
;;
|
;;
|
||||||
"checkout")
|
"checkout")
|
||||||
|
|||||||
@@ -1,455 +0,0 @@
|
|||||||
/* Pi-hole: A black hole for Internet advertisements
|
|
||||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
|
||||||
* Network-wide ad blocking via your own hardware.
|
|
||||||
*
|
|
||||||
* This file is copyright under the latest version of the EUPL.
|
|
||||||
* Please see LICENSE file for your rights under this license. */
|
|
||||||
|
|
||||||
/* Text Customisation Options ======> */
|
|
||||||
.title::before { content: "Website Blocked"; }
|
|
||||||
.altBtn::before { content: "Why am I here?"; }
|
|
||||||
.linkPH::before { content: "About Pi-hole"; }
|
|
||||||
.linkEmail::before { content: "Contact Admin"; }
|
|
||||||
|
|
||||||
#bpOutput.add::before { content: "Info"; }
|
|
||||||
#bpOutput.add::after { content: "The domain is being whitelisted..."; }
|
|
||||||
#bpOutput.error::before, .unhandled::before { content: "Error"; }
|
|
||||||
#bpOutput.unhandled::after { content: "An unhandled exception occurred. This may happen when your browser is unable to load jQuery, or when the webserver is denying access to the Pi-hole API."; }
|
|
||||||
#bpOutput.success::before { content: "Success"; }
|
|
||||||
#bpOutput.success::after { content: "Website has been whitelisted! You may need to flush your DNS cache"; }
|
|
||||||
|
|
||||||
.recentwl::before { content: "This site has been whitelisted. Please flush your DNS cache and/or restart your browser."; }
|
|
||||||
.unknown::before { content: "This website is not found in any of Pi-hole's blacklists. The reason you have arrived here is unknown."; }
|
|
||||||
.cname::before { content: "This site is an alias for "; } /* <a href="http://cname.com">cname.com</a> */
|
|
||||||
.cname::after { content: ", which may be blocked by Pi-hole."; }
|
|
||||||
|
|
||||||
.blacklist::before { content: "Manually Blacklisted"; }
|
|
||||||
.wildcard::before { content: "Manually Blacklisted by Wildcard"; }
|
|
||||||
.noblock::before { content: "Not found on any Blacklist"; }
|
|
||||||
|
|
||||||
#bpBlock::before { content: "Access to the following website has been denied:"; }
|
|
||||||
#bpFlag::before { content: "This is primarily due to being flagged as:"; }
|
|
||||||
|
|
||||||
#bpHelpTxt::before { content: "If you have an ongoing use for this website, please "; }
|
|
||||||
#bpHelpTxt a::before, #bpHelpTxt span::before { content: "ask the administrator"; }
|
|
||||||
#bpHelpTxt::after{ content: " of the Pi-hole on this network to have it whitelisted"; }
|
|
||||||
|
|
||||||
#bpBack::before { content: "Back to safety"; }
|
|
||||||
#bpInfo::before { content: "Technical Info"; }
|
|
||||||
#bpFoundIn::before { content: "This site is found in "; }
|
|
||||||
#bpFoundIn span::after { content: " of "; }
|
|
||||||
#bpFoundIn::after { content: " lists:"; }
|
|
||||||
#bpWhitelist::before { content: "Whitelist"; }
|
|
||||||
|
|
||||||
footer span::before { content: "Page generated on "; }
|
|
||||||
|
|
||||||
/* Hide whitelisting form entirely */
|
|
||||||
/* #bpWLButtons { display: none; } */
|
|
||||||
|
|
||||||
/* Text Customisation Options <=============================== */
|
|
||||||
|
|
||||||
/* http://necolas.github.io/normalize.css ======> */
|
|
||||||
html { font-family: sans-serif; line-height: 1.15; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; }
|
|
||||||
body { margin: 0; }
|
|
||||||
article, aside, footer, header, nav, section { display: block; }
|
|
||||||
h1 { font-size: 2em; margin: 0.67em 0; }
|
|
||||||
figcaption, figure, main { display: block; }
|
|
||||||
figure { margin: 1em 40px; }
|
|
||||||
hr { box-sizing: content-box; height: 0; overflow: visible; }
|
|
||||||
pre { font-family: monospace, monospace; font-size: 1em; }
|
|
||||||
a { background-color: transparent; -webkit-text-decoration-skip: objects; }
|
|
||||||
a:active, a:hover { outline-width: 0; }
|
|
||||||
abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; }
|
|
||||||
b, strong { font-weight: inherit; }
|
|
||||||
b, strong { font-weight: bolder; }
|
|
||||||
code, kbd, samp { font-family: monospace, monospace; font-size: 1em; }
|
|
||||||
dfn { font-style: italic; }
|
|
||||||
mark { background-color: #ff0; color: #000; }
|
|
||||||
small { font-size: 80%; }
|
|
||||||
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
|
|
||||||
sub { bottom: -0.25em; }
|
|
||||||
sup { top: -0.5em; }
|
|
||||||
audio, video { display: inline-block; }
|
|
||||||
audio:not([controls]) { display: none; height: 0; }
|
|
||||||
img { border-style: none; }
|
|
||||||
svg:not(:root) { overflow: hidden; }
|
|
||||||
button, input, optgroup, select, textarea { font-family: sans-serif; font-size: 100%; line-height: 1.15; margin: 0; }
|
|
||||||
button, input { overflow: visible; }
|
|
||||||
button, select { text-transform: none; }
|
|
||||||
button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; }
|
|
||||||
button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; }
|
|
||||||
button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; }
|
|
||||||
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
|
|
||||||
legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; }
|
|
||||||
progress { display: inline-block; vertical-align: baseline; }
|
|
||||||
textarea { overflow: auto; }
|
|
||||||
[type="checkbox"], [type="radio"] { box-sizing: border-box; padding: 0; }
|
|
||||||
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; }
|
|
||||||
[type="search"] { -webkit-appearance: textfield; outline-offset: -2px; }
|
|
||||||
[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
|
|
||||||
::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; }
|
|
||||||
details, menu { display: block; }
|
|
||||||
summary { display: list-item; }
|
|
||||||
canvas { display: inline-block; }
|
|
||||||
template { display: none; }
|
|
||||||
[hidden] { display: none; }
|
|
||||||
/* Normalize.css <=============================== */
|
|
||||||
|
|
||||||
html { font-size: 62.5%; }
|
|
||||||
|
|
||||||
a { color: #3c8dbc; text-decoration: none; }
|
|
||||||
a:hover { color: #72afda; text-decoration: underline; }
|
|
||||||
b { color: rgb(68, 68, 68); }
|
|
||||||
p { margin: 0; }
|
|
||||||
|
|
||||||
label, .buttons a {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
label, .buttons *:not([disabled]) { cursor: pointer; }
|
|
||||||
|
|
||||||
/* Touch device dark tap highlight */
|
|
||||||
header h1 a, label, .buttons * { -webkit-tap-highlight-color: transparent; }
|
|
||||||
|
|
||||||
/* Webkit Focus Glow */
|
|
||||||
textarea, input, button { outline: none; }
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "Source Sans Pro";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: local("Source Sans Pro Regular"), local("SourceSansPro-Regular"),
|
|
||||||
url("/admin/style/vendor/SourceSansPro/source-sans-pro-v13-latin-regular.woff2") format("woff2"),
|
|
||||||
url("/admin/style/vendor/SourceSansPro/source-sans-pro-v13-latin-regular.woff") format("woff");
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "Source Sans Pro";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: local("Source Sans Pro Bold"), local("SourceSansPro-Bold"),
|
|
||||||
url("/admin/style/vendor/SourceSansPro/source-sans-pro-v13-latin-700.woff2") format("woff2"),
|
|
||||||
url("/admin/style/vendor/SourceSansPro/source-sans-pro-v13-latin-700.woff") format("woff");
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: #dbdbdb url("/admin/img/boxed-bg.jpg") repeat fixed;
|
|
||||||
color: #333;
|
|
||||||
font: 1.4rem "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 2.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* User is greeted with a splash page when browsing to Pi-hole IP address */
|
|
||||||
#splashpage {
|
|
||||||
background: #222;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#splashpage img { margin: 5px; width: 256px; }
|
|
||||||
#splashpage b { color: inherit; }
|
|
||||||
|
|
||||||
#bpWrapper {
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 1250px;
|
|
||||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
background: #3c8dbc;
|
|
||||||
display: table;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
header h1, header h1 a, header .spc, header #bpAlt label {
|
|
||||||
display: table-cell;
|
|
||||||
color: #fff;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: middle;
|
|
||||||
height: 50px; /* Must match #bpAbout top value */
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 a {
|
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 400;
|
|
||||||
min-width: 230px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 a:hover, header #bpAlt:hover { background-color: rgba(0, 0, 0, 0.12); color: inherit; text-decoration: none; }
|
|
||||||
|
|
||||||
header .spc { width: 100%; }
|
|
||||||
|
|
||||||
header #bpAlt label {
|
|
||||||
background: url("/admin/img/logo.svg") no-repeat center left 15px;
|
|
||||||
background-size: 15px 23px;
|
|
||||||
padding: 0 15px;
|
|
||||||
text-indent: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type="checkbox"][id$="Toggle"] { display: none; }
|
|
||||||
[type="checkbox"][id$="Toggle"]:checked ~ #bpAbout,
|
|
||||||
[type="checkbox"][id$="Toggle"]:checked ~ #bpMoreInfo {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pihole_card {
|
|
||||||
width: 400px;
|
|
||||||
height: auto;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pihole_card p, #pihole_card a {
|
|
||||||
font-size: 13pt;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pihole_logo_splash {
|
|
||||||
height: auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Click anywhere else on screen to hide #bpAbout */
|
|
||||||
#bpAboutToggle:checked {
|
|
||||||
display: block;
|
|
||||||
height: 300px; /* VH Fallback */
|
|
||||||
height: 100vh;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpAbout {
|
|
||||||
background: #3c8dbc;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
border-right-width: 0;
|
|
||||||
box-shadow: -1px 1px 1px rgba(0, 0, 0, 0.12);
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: none;
|
|
||||||
font-size: 1.7rem;
|
|
||||||
top: 50px;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
width: 280px;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aboutPH {
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
display: block;
|
|
||||||
padding: 10px;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aboutImg {
|
|
||||||
background: url("/admin/img/logo.svg") no-repeat center;
|
|
||||||
background-size: 90px 90px;
|
|
||||||
height: 90px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2px;
|
|
||||||
width: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aboutPH p { margin: 10px 0; }
|
|
||||||
.aboutPH small { display: block; font-size: 1.2rem; }
|
|
||||||
|
|
||||||
.aboutLink {
|
|
||||||
background: #fff;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
display: table;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aboutLink a {
|
|
||||||
display: table-cell;
|
|
||||||
padding: 14px;
|
|
||||||
min-width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
background: #ecf0f5;
|
|
||||||
font-size: 1.65rem;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpOutput {
|
|
||||||
background: #00c0ef;
|
|
||||||
border-radius: 3px;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-top: 5px;
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpOutput::before {
|
|
||||||
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='14' viewBox='0 0 7 14'%3E%3Cpath fill='%23fff' d='M6 11a1.371 1.371 0 011 1v1a1.371 1.371 0 01-1 1H1a1.371 1.371 0 01-1-1v-1a1.371 1.371 0 011-1h1V8H1a1.371 1.371 0 01-1-1V6a1.371 1.371 0 011-1h3a1.371 1.371 0 011 1v5h1zM3.5 0A1.5 1.5 0 112 1.5 1.5 1.5 0 013.5 0z'/%3E%3C/svg%3E") no-repeat center left;
|
|
||||||
display: block;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
text-indent: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpOutput.hidden { display: none; }
|
|
||||||
#bpOutput.success { background: #00a65a; }
|
|
||||||
#bpOutput.error { background: #dd4b39; }
|
|
||||||
|
|
||||||
.blockMsg, .flagMsg {
|
|
||||||
font: 700 1.8rem Consolas, Courier, monospace;
|
|
||||||
padding: 5px 10px 10px;
|
|
||||||
text-indent: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpHelpTxt { padding-bottom: 10px; }
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
border-spacing: 5px 0;
|
|
||||||
display: table;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons * {
|
|
||||||
-moz-appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
border-radius: 3px;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
||||||
box-sizing: content-box;
|
|
||||||
display: table-cell;
|
|
||||||
font-size: 1.65rem;
|
|
||||||
margin-right: 5px;
|
|
||||||
min-height: 20px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: top;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons a:hover { text-decoration: none; }
|
|
||||||
|
|
||||||
/* Button hover dark overlay */
|
|
||||||
.buttons *:not(input):not([disabled]):hover {
|
|
||||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Button active shadow inset */
|
|
||||||
.buttons *:not([disabled]):not(input):active {
|
|
||||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input border color */
|
|
||||||
.buttons *:not([disabled]):hover, .buttons input:focus {
|
|
||||||
border-color: rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpButtons * { width: 50%; color: #fff; }
|
|
||||||
#bpBack { background-color: #00a65a; }
|
|
||||||
#bpInfo { background-color: #3c8dbc; }
|
|
||||||
#bpWhitelist { background-color: #dd4b39; }
|
|
||||||
|
|
||||||
#blockpage .buttons [type="password"][disabled] { color: rgba(0, 0, 0, 1); }
|
|
||||||
#blockpage .buttons [disabled] { color: rgba(0, 0, 0, 0.55); background-color: #e3e3e3; }
|
|
||||||
#blockpage .buttons [type="password"]:-ms-input-placeholder { color: rgba(51, 51, 51, 0.8); }
|
|
||||||
|
|
||||||
input[type="password"] { font-size: 1.5rem; }
|
|
||||||
|
|
||||||
@-webkit-keyframes slidein { from { max-height: 0; opacity: 0; } to { max-height: 300px; opacity: 1; } }
|
|
||||||
|
|
||||||
@keyframes slidein { from { max-height: 0; opacity: 0; } to { max-height: 300px; opacity: 1; } }
|
|
||||||
#bpMoreToggle:checked ~ #bpMoreInfo { display: block; margin-top: 8px; -webkit-animation: slidein 0.05s linear; animation: slidein 0.05s linear; }
|
|
||||||
#bpMoreInfo { display: none; margin-top: 10px; }
|
|
||||||
|
|
||||||
#bpQueryOutput {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
line-height: 1.65rem;
|
|
||||||
margin: 5px 0 0;
|
|
||||||
overflow: auto;
|
|
||||||
padding: 0 5px;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpQueryOutput span { margin-right: 4px; }
|
|
||||||
|
|
||||||
#bpWLButtons { width: auto; margin-top: 10px; }
|
|
||||||
#bpWLButtons * { display: inline-block; }
|
|
||||||
#bpWLDomain { display: none; }
|
|
||||||
#bpWLPassword { width: 160px; }
|
|
||||||
#bpWhitelist { color: #fff; }
|
|
||||||
|
|
||||||
footer {
|
|
||||||
background: #fff;
|
|
||||||
border-top: 1px solid #d2d6de;
|
|
||||||
color: #444;
|
|
||||||
font: 1.2rem Consolas, Courier, monospace;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive Content */
|
|
||||||
@media only screen and (max-width: 500px) {
|
|
||||||
h1 a {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
min-width: 170px;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer span::before {
|
|
||||||
content: "Generated ";
|
|
||||||
}
|
|
||||||
|
|
||||||
footer span {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width: 1251px) {
|
|
||||||
#bpWrapper, footer {
|
|
||||||
border-radius: 0 0 5px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bpAbout {
|
|
||||||
border-right-width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 400px) {
|
|
||||||
#pihole_card {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pihole_card p, #pihole_card a {
|
|
||||||
font-size: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 256px) {
|
|
||||||
#pihole_logo_splash {
|
|
||||||
width: 90% !important;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait fbcon=map:10 fbcon=font:VGA8x8 consoleblank=0
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# CONFIGURATION FILE FOR SETUPCON
|
|
||||||
|
|
||||||
# Consult the console-setup(5) manual page.
|
|
||||||
|
|
||||||
ACTIVE_CONSOLES="/dev/tty[1-6]"
|
|
||||||
|
|
||||||
CHARMAP="UTF-8"
|
|
||||||
|
|
||||||
# For best results with the Adafruit 2.8 LCD and Pi-hole's chronometer
|
|
||||||
CODESET="guess"
|
|
||||||
FONTFACE="Terminus"
|
|
||||||
FONTSIZE="10x20"
|
|
||||||
|
|
||||||
VIDEOMODE=
|
|
||||||
|
|
||||||
# The following is an example how to use a braille font
|
|
||||||
# FONT='lat9w-08.psf.gz brl-8x8.psf'
|
|
||||||
@@ -507,7 +507,7 @@
|
|||||||
# (using /etc/hosts) then that name can be specified as the
|
# (using /etc/hosts) then that name can be specified as the
|
||||||
# tftp_servername (the third option to dhcp-boot) and in that
|
# tftp_servername (the third option to dhcp-boot) and in that
|
||||||
# case dnsmasq resolves this name and returns the resultant IP
|
# case dnsmasq resolves this name and returns the resultant IP
|
||||||
# addresses in round robin fasion. This facility can be used to
|
# addresses in round robin fashion. This facility can be used to
|
||||||
# load balance the tftp load among a set of servers.
|
# load balance the tftp load among a set of servers.
|
||||||
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
|
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,6 @@ $serverName = htmlspecialchars($_SERVER["SERVER_NAME"]);
|
|||||||
// Remove external ipv6 brackets if any
|
// Remove external ipv6 brackets if any
|
||||||
$serverName = preg_replace('/^\[(.*)\]$/', '${1}', $serverName);
|
$serverName = preg_replace('/^\[(.*)\]$/', '${1}', $serverName);
|
||||||
|
|
||||||
if (!is_file("/etc/pihole/setupVars.conf"))
|
|
||||||
die("[ERROR] File not found: <code>/etc/pihole/setupVars.conf</code>");
|
|
||||||
|
|
||||||
// Get values from setupVars.conf
|
|
||||||
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
|
|
||||||
$svPasswd = !empty($setupVars["WEBPASSWORD"]);
|
|
||||||
$svEmail = (!empty($setupVars["ADMIN_EMAIL"]) && filter_var($setupVars["ADMIN_EMAIL"], FILTER_VALIDATE_EMAIL)) ? $setupVars["ADMIN_EMAIL"] : "";
|
|
||||||
unset($setupVars);
|
|
||||||
|
|
||||||
// Set landing page location, found within /var/www/html/
|
// Set landing page location, found within /var/www/html/
|
||||||
$landPage = "../landing.php";
|
$landPage = "../landing.php";
|
||||||
|
|
||||||
@@ -34,31 +25,17 @@ if (!empty($_SERVER["FQDN"])) {
|
|||||||
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
|
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set which extension types render as Block Page (Including "" for index.ext)
|
|
||||||
$validExtTypes = array("asp", "htm", "html", "php", "rss", "xml", "");
|
|
||||||
|
|
||||||
// Get extension of current URL
|
|
||||||
$currentUrlExt = pathinfo($_SERVER["REQUEST_URI"], PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
// Set mobile friendly viewport
|
|
||||||
$viewPort = '<meta name="viewport" content="width=device-width, initial-scale=1">';
|
|
||||||
|
|
||||||
// Set response header
|
|
||||||
function setHeader($type = "x") {
|
|
||||||
header("X-Pi-hole: A black hole for Internet advertisements.");
|
|
||||||
if (isset($type) && $type === "js") header("Content-Type: application/javascript");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine block page type
|
// Determine block page type
|
||||||
if ($serverName === "pi.hole"
|
if ($serverName === "pi.hole"
|
||||||
|| (!empty($_SERVER["VIRTUAL_HOST"]) && $serverName === $_SERVER["VIRTUAL_HOST"])) {
|
|| (!empty($_SERVER["VIRTUAL_HOST"]) && $serverName === $_SERVER["VIRTUAL_HOST"])) {
|
||||||
// Redirect to Web Interface
|
// Redirect to Web Interface
|
||||||
exit(header("Location: /admin"));
|
header("Location: /admin");
|
||||||
|
exit();
|
||||||
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
|
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
|
||||||
// When directly browsing via IP or authorized hostname
|
// When directly browsing via IP or authorized hostname
|
||||||
// Render splash/landing page based off presence of $landPage file
|
// Render splash/landing page based off presence of $landPage file
|
||||||
// Unset variables so as to not be included in $landPage or $splashPage
|
// Unset variables so as to not be included in $landPage or $splashPage
|
||||||
unset($svPasswd, $svEmail, $authorizedHosts, $validExtTypes, $currentUrlExt);
|
unset($authorizedHosts);
|
||||||
// If $landPage file is present
|
// If $landPage file is present
|
||||||
if (is_file(getcwd()."/$landPage")) {
|
if (is_file(getcwd()."/$landPage")) {
|
||||||
unset($serverName, $viewPort); // unset extra variables not to be included in $landpage
|
unset($serverName, $viewPort); // unset extra variables not to be included in $landpage
|
||||||
@@ -71,325 +48,34 @@ if ($serverName === "pi.hole"
|
|||||||
<html lang='en'>
|
<html lang='en'>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
$viewPort
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||||
<title>● $serverName</title>
|
<title>● $serverName</title>
|
||||||
<link rel='stylesheet' href='/pihole/blockingpage.css'>
|
|
||||||
<link rel='shortcut icon' href='/admin/img/favicons/favicon.ico' type='image/x-icon'>
|
<link rel='shortcut icon' href='/admin/img/favicons/favicon.ico' type='image/x-icon'>
|
||||||
|
<style>
|
||||||
|
html, body { height: 100% }
|
||||||
|
body { margin: 0; font: 13pt "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; }
|
||||||
|
body { background: #222; color: rgba(255, 255, 255, 0.7); text-align: center; }
|
||||||
|
p { margin: 0; }
|
||||||
|
a { color: #3c8dbc; text-decoration: none; }
|
||||||
|
a:hover { color: #72afda; text-decoration: underline; }
|
||||||
|
#splashpage { display: flex; align-items: center; justify-content: center; }
|
||||||
|
#splashpage img { margin: 5px; width: 256px; }
|
||||||
|
#splashpage b { color: inherit; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body id='splashpage'>
|
<body id='splashpage'>
|
||||||
<div id="pihole_card">
|
<div>
|
||||||
<img src='/admin/img/logo.svg' alt='Pi-hole logo' id="pihole_logo_splash" />
|
<img src='/admin/img/logo.svg' alt='Pi-hole logo' width='256' height='377'>
|
||||||
<p>Pi-<strong>hole</strong>: Your black hole for Internet advertisements</p>
|
<br>
|
||||||
<a href='/admin'>Did you mean to go to the admin panel?</a>
|
<p>Pi-<strong>hole</strong>: Your black hole for Internet advertisements</p>
|
||||||
|
<a href='/admin'>Did you mean to go to the admin panel?</a>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
EOT;
|
EOT;
|
||||||
exit($splashPage);
|
exit($splashPage);
|
||||||
} elseif ($currentUrlExt === "js") {
|
|
||||||
// Serve Pi-hole JavaScript for blocked domains requesting JS
|
|
||||||
exit(setHeader("js").'var x = "Pi-hole: A black hole for Internet advertisements."');
|
|
||||||
} elseif (strpos($_SERVER["REQUEST_URI"], "?") !== FALSE && isset($_SERVER["HTTP_REFERER"])) {
|
|
||||||
// Serve blank image upon receiving REQUEST_URI w/ query string & HTTP_REFERRER
|
|
||||||
// e.g: An iframe of a blocked domain
|
|
||||||
exit(setHeader().'<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"><script>window.close();</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=">
|
|
||||||
</body>
|
|
||||||
</html>');
|
|
||||||
} elseif (!in_array($currentUrlExt, $validExtTypes) || substr_count($_SERVER["REQUEST_URI"], "?")) {
|
|
||||||
// Serve SVG upon receiving non $validExtTypes URL extension or query string
|
|
||||||
// e.g: Not an iframe of a blocked domain, such as when browsing to a file/query directly
|
|
||||||
// QoL addition: Allow the SVG to be clicked on in order to quickly show the full Block Page
|
|
||||||
$blockImg = '<a href="/">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="110" height="16">
|
|
||||||
<circle cx="8" cy="8" r="7" fill="none" stroke="rgba(152,2,2,.5)" stroke-width="2"/>
|
|
||||||
<path fill="rgba(152,2,2,.5)" d="M11.526 3.04l1.414 1.415-8.485 8.485-1.414-1.414z"/>
|
|
||||||
<text x="19.3" y="12" opacity=".3" style="font:11px Arial">
|
|
||||||
Blocked by Pi-hole
|
|
||||||
</text>
|
|
||||||
</svg>
|
|
||||||
</a>';
|
|
||||||
exit(setHeader()."<!doctype html>
|
|
||||||
<html lang='en'>
|
|
||||||
<head>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
$viewPort
|
|
||||||
</head>
|
|
||||||
<body>$blockImg</body>
|
|
||||||
</html>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start processing Block Page from here */
|
header("HTTP/1.1 404 Not Found");
|
||||||
|
exit();
|
||||||
// Define admin email address text based off $svEmail presence
|
|
||||||
$bpAskAdmin = !empty($svEmail) ? '<a href="mailto:'.$svEmail.'?subject=Site Blocked: '.$serverName.'"></a>' : "<span/>";
|
|
||||||
|
|
||||||
// Get possible non-standard location of FTL's database
|
|
||||||
$FTLsettings = parse_ini_file("/etc/pihole/pihole-FTL.conf");
|
|
||||||
if (isset($FTLsettings["GRAVITYDB"])) {
|
|
||||||
$gravityDBFile = $FTLsettings["GRAVITYDB"];
|
|
||||||
} else {
|
|
||||||
$gravityDBFile = "/etc/pihole/gravity.db";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to gravity.db
|
|
||||||
try {
|
|
||||||
$db = new SQLite3($gravityDBFile, SQLITE3_OPEN_READONLY);
|
|
||||||
} catch (Exception $exception) {
|
|
||||||
die("[ERROR]: Failed to connect to gravity.db");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all adlist addresses
|
|
||||||
$adlistResults = $db->query("SELECT address FROM vw_adlist");
|
|
||||||
$adlistsUrls = array();
|
|
||||||
while ($row = $adlistResults->fetchArray()) {
|
|
||||||
array_push($adlistsUrls, $row[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($adlistsUrls))
|
|
||||||
die("[ERROR]: There are no adlists enabled");
|
|
||||||
|
|
||||||
// Get total number of blocklists (Including Whitelist, Blacklist & Wildcard lists)
|
|
||||||
$adlistsCount = count($adlistsUrls) + 3;
|
|
||||||
|
|
||||||
// Set query timeout
|
|
||||||
ini_set("default_socket_timeout", 3);
|
|
||||||
|
|
||||||
// Logic for querying blocklists
|
|
||||||
function queryAds($serverName) {
|
|
||||||
// Determine the time it takes while querying adlists
|
|
||||||
$preQueryTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
|
|
||||||
$queryAdsURL = sprintf(
|
|
||||||
"http://127.0.0.1:%s/admin/scripts/pi-hole/php/queryads.php?domain=%s&bp",
|
|
||||||
$_SERVER["SERVER_PORT"],
|
|
||||||
$serverName
|
|
||||||
);
|
|
||||||
$queryAds = file($queryAdsURL, FILE_IGNORE_NEW_LINES);
|
|
||||||
$queryAds = array_values(array_filter(preg_replace("/data:\s+/", "", $queryAds)));
|
|
||||||
$queryTime = sprintf("%.0f", (microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"]) - $preQueryTime);
|
|
||||||
|
|
||||||
// Exception Handling
|
|
||||||
try {
|
|
||||||
// Define Exceptions
|
|
||||||
if (strpos($queryAds[0], "No exact results") !== FALSE) {
|
|
||||||
// Return "none" into $queryAds array
|
|
||||||
return array("0" => "none");
|
|
||||||
} else if ($queryTime >= ini_get("default_socket_timeout")) {
|
|
||||||
// Connection Timeout
|
|
||||||
throw new Exception ("Connection timeout (".ini_get("default_socket_timeout")."s)");
|
|
||||||
} elseif (!strpos($queryAds[0], ".") !== false) {
|
|
||||||
// Unknown $queryAds output
|
|
||||||
throw new Exception ("Unhandled error message (<code>$queryAds[0]</code>)");
|
|
||||||
}
|
|
||||||
return $queryAds;
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Return exception as array
|
|
||||||
return array("0" => "error", "1" => $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get results of queryads.php exact search
|
|
||||||
$queryAds = queryAds($serverName);
|
|
||||||
|
|
||||||
// Pass error through to Block Page
|
|
||||||
if ($queryAds[0] === "error")
|
|
||||||
die("[ERROR]: Unable to parse results from <i>queryads.php</i>: <code>".$queryAds[1]."</code>");
|
|
||||||
|
|
||||||
// Count total number of matching blocklists
|
|
||||||
$featuredTotal = count($queryAds);
|
|
||||||
|
|
||||||
// Place results into key => value array
|
|
||||||
$queryResults = null;
|
|
||||||
foreach ($queryAds as $str) {
|
|
||||||
$value = explode(" ", $str);
|
|
||||||
@$queryResults[$value[0]] .= "$value[1]";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine if domain has been blacklisted, whitelisted, wildcarded or CNAME blocked
|
|
||||||
if (strpos($queryAds[0], "blacklist") !== FALSE) {
|
|
||||||
$notableFlagClass = "blacklist";
|
|
||||||
$adlistsUrls = array("π" => substr($queryAds[0], 2));
|
|
||||||
} elseif (strpos($queryAds[0], "whitelist") !== FALSE) {
|
|
||||||
$notableFlagClass = "noblock";
|
|
||||||
$adlistsUrls = array("π" => substr($queryAds[0], 2));
|
|
||||||
$wlInfo = "recentwl";
|
|
||||||
} elseif (strpos($queryAds[0], "wildcard") !== FALSE) {
|
|
||||||
$notableFlagClass = "wildcard";
|
|
||||||
$adlistsUrls = array("π" => substr($queryAds[0], 2));
|
|
||||||
} elseif ($queryAds[0] === "none") {
|
|
||||||
$featuredTotal = "0";
|
|
||||||
$notableFlagClass = "noblock";
|
|
||||||
|
|
||||||
// QoL addition: Determine appropriate info message if CNAME exists
|
|
||||||
// Suggests to the user that $serverName has a CNAME (alias) that may be blocked
|
|
||||||
$dnsRecord = dns_get_record("$serverName")[0];
|
|
||||||
if (array_key_exists("target", $dnsRecord)) {
|
|
||||||
$wlInfo = $dnsRecord['target'];
|
|
||||||
} else {
|
|
||||||
$wlInfo = "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set #bpOutput notification
|
|
||||||
$wlOutputClass = (isset($wlInfo) && $wlInfo === "recentwl") ? $wlInfo : "hidden";
|
|
||||||
$wlOutput = (isset($wlInfo) && $wlInfo !== "recentwl") ? "<a href='http://$wlInfo'>$wlInfo</a>" : "";
|
|
||||||
|
|
||||||
// Get Pi-hole Core version
|
|
||||||
$phVersion = exec("cd /etc/.pihole/ && git describe --long --tags");
|
|
||||||
|
|
||||||
// Print $execTime on development branches
|
|
||||||
// Testing for - is marginally faster than "git rev-parse --abbrev-ref HEAD"
|
|
||||||
if (explode("-", $phVersion)[1] != "0")
|
|
||||||
$execTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
|
|
||||||
|
|
||||||
// Please Note: Text is added via CSS to allow an admin to provide a localized
|
|
||||||
// language without the need to edit this file
|
|
||||||
|
|
||||||
setHeader();
|
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
|
||||||
<!-- Pi-hole: A black hole for Internet advertisements
|
|
||||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
|
||||||
* Network-wide ad blocking via your own hardware.
|
|
||||||
*
|
|
||||||
* This file is copyright under the latest version of the EUPL. -->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<?=$viewPort ?>
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
<meta http-equiv="x-dns-prefetch-control" content="off">
|
|
||||||
<link rel="stylesheet" href="pihole/blockingpage.css">
|
|
||||||
<link rel="shortcut icon" href="admin/img/favicons/favicon.ico" type="image/x-icon">
|
|
||||||
<title>● <?=$serverName ?></title>
|
|
||||||
<script src="admin/scripts/vendor/jquery.min.js"></script>
|
|
||||||
<script>
|
|
||||||
window.onload = function () {
|
|
||||||
<?php
|
|
||||||
// Remove href fallback from "Back to safety" button
|
|
||||||
if ($featuredTotal > 0) {
|
|
||||||
echo '$("#bpBack").removeAttr("href");';
|
|
||||||
|
|
||||||
// Enable whitelisting if JS is available
|
|
||||||
echo '$("#bpWhitelist").prop("disabled", false);';
|
|
||||||
|
|
||||||
// Enable password input if necessary
|
|
||||||
if (!empty($svPasswd)) {
|
|
||||||
echo '$("#bpWLPassword").attr("placeholder", "Password");';
|
|
||||||
echo '$("#bpWLPassword").prop("disabled", false);';
|
|
||||||
}
|
|
||||||
// Otherwise hide the input
|
|
||||||
else {
|
|
||||||
echo '$("#bpWLPassword").hide();';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body id="blockpage"><div id="bpWrapper">
|
|
||||||
<header>
|
|
||||||
<h1 id="bpTitle">
|
|
||||||
<a class="title" href="/"><?php //Website Blocked ?></a>
|
|
||||||
</h1>
|
|
||||||
<div class="spc"></div>
|
|
||||||
|
|
||||||
<input id="bpAboutToggle" type="checkbox">
|
|
||||||
<div id="bpAbout">
|
|
||||||
<div class="aboutPH">
|
|
||||||
<div class="aboutImg"></div>
|
|
||||||
<p>Open Source Ad Blocker
|
|
||||||
<small>Designed for Raspberry Pi</small>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="aboutLink">
|
|
||||||
<a class="linkPH" href="https://docs.pi-hole.net/"><?php //About PH ?></a>
|
|
||||||
<?php if (!empty($svEmail)) echo '<a class="linkEmail" href="mailto:'.$svEmail.'"></a>'; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="bpAlt">
|
|
||||||
<label class="altBtn" for="bpAboutToggle"><?php //Why am I here? ?></label>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div id="bpOutput" class="<?=$wlOutputClass ?>"><?=$wlOutput ?></div>
|
|
||||||
<div id="bpBlock">
|
|
||||||
<p class="blockMsg"><?=$serverName ?></p>
|
|
||||||
</div>
|
|
||||||
<?php if(isset($notableFlagClass)) { ?>
|
|
||||||
<div id="bpFlag">
|
|
||||||
<p class="flagMsg <?=$notableFlagClass ?>"></p>
|
|
||||||
</div>
|
|
||||||
<?php } ?>
|
|
||||||
<div id="bpHelpTxt"><?=$bpAskAdmin ?></div>
|
|
||||||
<div id="bpButtons" class="buttons">
|
|
||||||
<a id="bpBack" onclick="javascript:history.back()" href="about:home"></a>
|
|
||||||
<?php if ($featuredTotal > 0) echo '<label id="bpInfo" for="bpMoreToggle"></label>'; ?>
|
|
||||||
</div>
|
|
||||||
<input id="bpMoreToggle" type="checkbox">
|
|
||||||
<div id="bpMoreInfo">
|
|
||||||
<span id="bpFoundIn"><span><?=$featuredTotal ?></span><?=$adlistsCount ?></span>
|
|
||||||
<pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryResults as $num => $value) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
|
|
||||||
|
|
||||||
<form id="bpWLButtons" class="buttons">
|
|
||||||
<input id="bpWLDomain" type="text" value="<?=$serverName ?>" disabled>
|
|
||||||
<input id="bpWLPassword" type="password" placeholder="JavaScript disabled" disabled>
|
|
||||||
<button id="bpWhitelist" type="button" disabled></button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer><span><?=date("l g:i A, F dS"); ?>.</span> Pi-hole <?=$phVersion ?> (<?=gethostname()."/".$_SERVER["SERVER_ADDR"]; if (isset($execTime)) printf("/%.2fs", $execTime); ?>)</footer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function add() {
|
|
||||||
$("#bpOutput").removeClass("hidden error exception");
|
|
||||||
$("#bpOutput").addClass("add");
|
|
||||||
var domain = "<?=$serverName ?>";
|
|
||||||
var pw = $("#bpWLPassword");
|
|
||||||
if(domain.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
url: "/admin/scripts/pi-hole/php/add.php",
|
|
||||||
method: "post",
|
|
||||||
data: {"domain":domain, "list":"white", "pw":pw.val()},
|
|
||||||
success: function(response) {
|
|
||||||
if(response.indexOf("Pi-hole blocking") !== -1) {
|
|
||||||
setTimeout(function(){window.location.reload(1);}, 10000);
|
|
||||||
$("#bpOutput").removeClass("add");
|
|
||||||
$("#bpOutput").addClass("success");
|
|
||||||
$("#bpOutput").html("");
|
|
||||||
} else {
|
|
||||||
$("#bpOutput").removeClass("add");
|
|
||||||
$("#bpOutput").addClass("error");
|
|
||||||
$("#bpOutput").html(""+response+"");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(jqXHR, exception) {
|
|
||||||
$("#bpOutput").removeClass("add");
|
|
||||||
$("#bpOutput").addClass("exception");
|
|
||||||
$("#bpOutput").html("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
<?php if ($featuredTotal > 0) { ?>
|
|
||||||
$(document).keypress(function(e) {
|
|
||||||
if(e.which === 13 && $("#bpWLPassword").is(":focus")) {
|
|
||||||
add();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$("#bpWhitelist").on("click", function() {
|
|
||||||
add();
|
|
||||||
});
|
|
||||||
<?php } ?>
|
|
||||||
</script>
|
|
||||||
</body></html>
|
|
||||||
|
|||||||
@@ -28,14 +28,21 @@ server.modules = (
|
|||||||
server.document-root = "/var/www/html"
|
server.document-root = "/var/www/html"
|
||||||
server.error-handler-404 = "/pihole/index.php"
|
server.error-handler-404 = "/pihole/index.php"
|
||||||
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
||||||
server.errorlog = "/var/log/lighttpd/error.log"
|
server.errorlog = "/var/log/lighttpd/error-pihole.log"
|
||||||
server.pid-file = "/run/lighttpd.pid"
|
server.pid-file = "/run/lighttpd.pid"
|
||||||
server.username = "www-data"
|
server.username = "www-data"
|
||||||
server.groupname = "www-data"
|
server.groupname = "www-data"
|
||||||
|
# For lighttpd version 1.4.46 or above, the port can be overwritten in `/etc/lighttpd/external.conf` using the := operator
|
||||||
|
# e.g. server.port := 8000
|
||||||
server.port = 80
|
server.port = 80
|
||||||
accesslog.filename = "/var/log/lighttpd/access.log"
|
accesslog.filename = "/var/log/lighttpd/access-pihole.log"
|
||||||
accesslog.format = "%{%s}t|%V|%r|%s|%b"
|
accesslog.format = "%{%s}t|%V|%r|%s|%b"
|
||||||
|
|
||||||
|
# Allow streaming response
|
||||||
|
# reference: https://redmine.lighttpd.net/projects/lighttpd/wiki/Server_stream-response-bodyDetails
|
||||||
|
server.stream-response-body = 1
|
||||||
|
#ssl.read-ahead = "disable"
|
||||||
|
|
||||||
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
||||||
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
|
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
|
||||||
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
||||||
@@ -73,10 +80,21 @@ include_shell "find /etc/lighttpd/conf-enabled -name '*.conf' -a ! -name 'letsen
|
|||||||
|
|
||||||
# If the URL starts with /admin, it is the Web interface
|
# If the URL starts with /admin, it is the Web interface
|
||||||
$HTTP["url"] =~ "^/admin/" {
|
$HTTP["url"] =~ "^/admin/" {
|
||||||
# Create a response header for debugging using curl -I
|
# X-Pi-hole is a response header for debugging using curl -I
|
||||||
|
# X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >.
|
||||||
|
# X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input.
|
||||||
|
# X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code.
|
||||||
|
# Content-Security-Policy tells the browser where resources are allowed to be loaded and if it’s allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS).
|
||||||
|
# X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
|
||||||
|
# Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all.
|
||||||
setenv.add-response-header = (
|
setenv.add-response-header = (
|
||||||
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
||||||
"X-Frame-Options" => "DENY"
|
"X-Frame-Options" => "DENY",
|
||||||
|
"X-XSS-Protection" => "1; mode=block",
|
||||||
|
"X-Content-Type-Options" => "nosniff",
|
||||||
|
"Content-Security-Policy" => "default-src 'self' 'unsafe-inline';",
|
||||||
|
"X-Permitted-Cross-Domain-Policies" => "none",
|
||||||
|
"Referrer-Policy" => "same-origin"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,14 +29,21 @@ server.modules = (
|
|||||||
server.document-root = "/var/www/html"
|
server.document-root = "/var/www/html"
|
||||||
server.error-handler-404 = "/pihole/index.php"
|
server.error-handler-404 = "/pihole/index.php"
|
||||||
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
|
||||||
server.errorlog = "/var/log/lighttpd/error.log"
|
server.errorlog = "/var/log/lighttpd/error-pihole.log"
|
||||||
server.pid-file = "/run/lighttpd.pid"
|
server.pid-file = "/run/lighttpd.pid"
|
||||||
server.username = "lighttpd"
|
server.username = "lighttpd"
|
||||||
server.groupname = "lighttpd"
|
server.groupname = "lighttpd"
|
||||||
|
# For lighttpd version 1.4.46 or above, the port can be overwritten in `/etc/lighttpd/external.conf` using the := operator
|
||||||
|
# e.g. server.port := 8000
|
||||||
server.port = 80
|
server.port = 80
|
||||||
accesslog.filename = "/var/log/lighttpd/access.log"
|
accesslog.filename = "/var/log/lighttpd/access-pihole.log"
|
||||||
accesslog.format = "%{%s}t|%V|%r|%s|%b"
|
accesslog.format = "%{%s}t|%V|%r|%s|%b"
|
||||||
|
|
||||||
|
# Allow streaming response
|
||||||
|
# reference: https://redmine.lighttpd.net/projects/lighttpd/wiki/Server_stream-response-bodyDetails
|
||||||
|
server.stream-response-body = 1
|
||||||
|
#ssl.read-ahead = "disable"
|
||||||
|
|
||||||
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
|
||||||
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
|
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
|
||||||
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
|
||||||
@@ -81,10 +88,21 @@ fastcgi.server = (
|
|||||||
|
|
||||||
# If the URL starts with /admin, it is the Web interface
|
# If the URL starts with /admin, it is the Web interface
|
||||||
$HTTP["url"] =~ "^/admin/" {
|
$HTTP["url"] =~ "^/admin/" {
|
||||||
# Create a response header for debugging using curl -I
|
# X-Pi-hole is a response header for debugging using curl -I
|
||||||
|
# X-Frame-Options prevents clickjacking attacks and helps ensure your content is not embedded into other sites via < frame >, < iframe > or < object >.
|
||||||
|
# X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. This is important because it tells the browser to block the response if a malicious script has been inserted from a user input.
|
||||||
|
# X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. This is important because the browser will only load external resources if their content-type matches what is expected, and not malicious hidden code.
|
||||||
|
# Content-Security-Policy tells the browser where resources are allowed to be loaded and if it’s allowed to parse/run inline styles or Javascript. This is important because it prevents content injection attacks, such as Cross Site Scripting (XSS).
|
||||||
|
# X-Permitted-Cross-Domain-Policies is an XML document that grants a web client, such as Adobe Flash Player or Adobe Acrobat (though not necessarily limited to these), permission to handle data across domains.
|
||||||
|
# Referrer-Policy allows control/restriction of the amount of information present in the referral header for links away from your page—the URL path or even if the header is sent at all.
|
||||||
setenv.add-response-header = (
|
setenv.add-response-header = (
|
||||||
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
"X-Pi-hole" => "The Pi-hole Web interface is working!",
|
||||||
"X-Frame-Options" => "DENY"
|
"X-Frame-Options" => "DENY",
|
||||||
|
"X-XSS-Protection" => "1; mode=block",
|
||||||
|
"X-Content-Type-Options" => "nosniff",
|
||||||
|
"Content-Security-Policy" => "default-src 'self' 'unsafe-inline';",
|
||||||
|
"X-Permitted-Cross-Domain-Policies" => "none",
|
||||||
|
"Referrer-Policy" => "same-origin"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,10 +11,9 @@
|
|||||||
source "/opt/pihole/COL_TABLE"
|
source "/opt/pihole/COL_TABLE"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " yn
|
read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer
|
||||||
case ${yn} in
|
case ${answer} in
|
||||||
[Yy]* ) break;;
|
[Yy]* ) break;;
|
||||||
[Nn]* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
|
|
||||||
* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
|
* ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -37,7 +36,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
|
||||||
PH_TEST="true"
|
SKIP_INSTALL="true"
|
||||||
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
|
||||||
# setupVars set in basic-install.sh
|
# setupVars set in basic-install.sh
|
||||||
source "${setupVars}"
|
source "${setupVars}"
|
||||||
@@ -45,8 +44,8 @@ source "${setupVars}"
|
|||||||
# package_manager_detect() sourced from basic-install.sh
|
# package_manager_detect() sourced from basic-install.sh
|
||||||
package_manager_detect
|
package_manager_detect
|
||||||
|
|
||||||
# Install packages used by the Pi-hole
|
# Uninstall packages used by the Pi-hole
|
||||||
DEPS=("${INSTALLER_DEPS[@]}" "${PIHOLE_DEPS[@]}")
|
DEPS=("${INSTALLER_DEPS[@]}" "${PIHOLE_DEPS[@]}" "${OS_CHECK_DEPS[@]}")
|
||||||
if [[ "${INSTALL_WEB_SERVER}" == true ]]; then
|
if [[ "${INSTALL_WEB_SERVER}" == true ]]; then
|
||||||
# Install the Web dependencies
|
# Install the Web dependencies
|
||||||
DEPS+=("${PIHOLE_WEB_DEPS[@]}")
|
DEPS+=("${PIHOLE_WEB_DEPS[@]}")
|
||||||
@@ -76,8 +75,8 @@ removeAndPurge() {
|
|||||||
for i in "${DEPS[@]}"; do
|
for i in "${DEPS[@]}"; do
|
||||||
if package_check "${i}" > /dev/null; then
|
if package_check "${i}" > /dev/null; then
|
||||||
while true; do
|
while true; do
|
||||||
read -rp " ${QST} Do you wish to remove ${COL_WHITE}${i}${COL_NC} from your system? [Y/N] " yn
|
read -rp " ${QST} Do you wish to remove ${COL_WHITE}${i}${COL_NC} from your system? [Y/N] " answer
|
||||||
case ${yn} in
|
case ${answer} in
|
||||||
[Yy]* )
|
[Yy]* )
|
||||||
echo -ne " ${INFO} Removing ${i}...";
|
echo -ne " ${INFO} Removing ${i}...";
|
||||||
${SUDO} "${PKG_REMOVE[@]}" "${i}" &> /dev/null;
|
${SUDO} "${PKG_REMOVE[@]}" "${i}" &> /dev/null;
|
||||||
@@ -147,6 +146,7 @@ removeNoPurge() {
|
|||||||
${SUDO} rm -f /etc/dnsmasq.d/01-pihole.conf &> /dev/null
|
${SUDO} rm -f /etc/dnsmasq.d/01-pihole.conf &> /dev/null
|
||||||
${SUDO} rm -f /etc/dnsmasq.d/06-rfc6761.conf &> /dev/null
|
${SUDO} rm -f /etc/dnsmasq.d/06-rfc6761.conf &> /dev/null
|
||||||
${SUDO} rm -rf /var/log/*pihole* &> /dev/null
|
${SUDO} rm -rf /var/log/*pihole* &> /dev/null
|
||||||
|
${SUDO} rm -rf /var/log/pihole/*pihole* &> /dev/null
|
||||||
${SUDO} rm -rf /etc/pihole/ &> /dev/null
|
${SUDO} rm -rf /etc/pihole/ &> /dev/null
|
||||||
${SUDO} rm -rf /etc/.pihole/ &> /dev/null
|
${SUDO} rm -rf /etc/.pihole/ &> /dev/null
|
||||||
${SUDO} rm -rf /opt/pihole/ &> /dev/null
|
${SUDO} rm -rf /opt/pihole/ &> /dev/null
|
||||||
@@ -215,8 +215,8 @@ while true; do
|
|||||||
echo -n "${i} "
|
echo -n "${i} "
|
||||||
done
|
done
|
||||||
echo "${COL_NC}"
|
echo "${COL_NC}"
|
||||||
read -rp " ${QST} Do you wish to go through each dependency for removal? (Choosing No will leave all dependencies installed) [Y/n] " yn
|
read -rp " ${QST} Do you wish to go through each dependency for removal? (Choosing No will leave all dependencies installed) [Y/n] " answer
|
||||||
case ${yn} in
|
case ${answer} in
|
||||||
[Yy]* ) removeAndPurge; break;;
|
[Yy]* ) removeAndPurge; break;;
|
||||||
[Nn]* ) removeNoPurge; break;;
|
[Nn]* ) removeNoPurge; break;;
|
||||||
* ) removeAndPurge; break;;
|
* ) removeAndPurge; break;;
|
||||||
|
|||||||
151
gravity.sh
151
gravity.sh
@@ -40,6 +40,7 @@ gravityDBschema="${piholeGitDir}/advanced/Templates/gravity.db.sql"
|
|||||||
gravityDBcopy="${piholeGitDir}/advanced/Templates/gravity_copy.sql"
|
gravityDBcopy="${piholeGitDir}/advanced/Templates/gravity_copy.sql"
|
||||||
|
|
||||||
domainsExtension="domains"
|
domainsExtension="domains"
|
||||||
|
curl_connect_timeout=10
|
||||||
|
|
||||||
# Source setupVars from install script
|
# Source setupVars from install script
|
||||||
setupVars="${piholeDir}/setupVars.conf"
|
setupVars="${piholeDir}/setupVars.conf"
|
||||||
@@ -73,9 +74,9 @@ if [[ -r "${piholeDir}/pihole.conf" ]]; then
|
|||||||
echo -e " ${COL_LIGHT_RED}Ignoring overrides specified within pihole.conf! ${COL_NC}"
|
echo -e " ${COL_LIGHT_RED}Ignoring overrides specified within pihole.conf! ${COL_NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate new sqlite3 file from schema template
|
# Generate new SQLite3 file from schema template
|
||||||
generate_gravity_database() {
|
generate_gravity_database() {
|
||||||
if ! sqlite3 "${gravityDBfile}" < "${gravityDBschema}"; then
|
if ! pihole-FTL sqlite3 "${gravityDBfile}" < "${gravityDBschema}"; then
|
||||||
echo -e " ${CROSS} Unable to create ${gravityDBfile}"
|
echo -e " ${CROSS} Unable to create ${gravityDBfile}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -85,12 +86,12 @@ generate_gravity_database() {
|
|||||||
|
|
||||||
# Copy data from old to new database file and swap them
|
# Copy data from old to new database file and swap them
|
||||||
gravity_swap_databases() {
|
gravity_swap_databases() {
|
||||||
local str copyGravity
|
local str copyGravity oldAvail
|
||||||
str="Building tree"
|
str="Building tree"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
|
|
||||||
# The index is intentionally not UNIQUE as poor quality adlists may contain domains more than once
|
# The index is intentionally not UNIQUE as poor quality adlists may contain domains more than once
|
||||||
output=$( { sqlite3 "${gravityTEMPfile}" "CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1 )
|
output=$( { pihole-FTL sqlite3 "${gravityTEMPfile}" "CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -102,22 +103,6 @@ gravity_swap_databases() {
|
|||||||
str="Swapping databases"
|
str="Swapping databases"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
|
|
||||||
# Gravity copying SQL script
|
|
||||||
copyGravity="$(cat "${gravityDBcopy}")"
|
|
||||||
if [[ "${gravityDBfile}" != "${gravityDBfile_default}" ]]; then
|
|
||||||
# Replace default gravity script location by custom location
|
|
||||||
copyGravity="${copyGravity//"${gravityDBfile_default}"/"${gravityDBfile}"}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
output=$( { sqlite3 "${gravityTEMPfile}" <<< "${copyGravity}"; } 2>&1 )
|
|
||||||
status="$?"
|
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
|
||||||
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo -e "${OVER} ${TICK} ${str}"
|
|
||||||
|
|
||||||
# Swap databases and remove or conditionally rename old database
|
# Swap databases and remove or conditionally rename old database
|
||||||
# Number of available blocks on disk
|
# Number of available blocks on disk
|
||||||
availableBlocks=$(stat -f --format "%a" "${gravityDIR}")
|
availableBlocks=$(stat -f --format "%a" "${gravityDIR}")
|
||||||
@@ -125,18 +110,24 @@ gravity_swap_databases() {
|
|||||||
gravityBlocks=$(stat --format "%b" ${gravityDBfile})
|
gravityBlocks=$(stat --format "%b" ${gravityDBfile})
|
||||||
# Only keep the old database if available disk space is at least twice the size of the existing gravity.db.
|
# Only keep the old database if available disk space is at least twice the size of the existing gravity.db.
|
||||||
# Better be safe than sorry...
|
# Better be safe than sorry...
|
||||||
|
oldAvail=false
|
||||||
if [ "${availableBlocks}" -gt "$((gravityBlocks * 2))" ] && [ -f "${gravityDBfile}" ]; then
|
if [ "${availableBlocks}" -gt "$((gravityBlocks * 2))" ] && [ -f "${gravityDBfile}" ]; then
|
||||||
echo -e " ${TICK} The old database remains available."
|
oldAvail=true
|
||||||
mv "${gravityDBfile}" "${gravityOLDfile}"
|
mv "${gravityDBfile}" "${gravityOLDfile}"
|
||||||
else
|
else
|
||||||
rm "${gravityDBfile}"
|
rm "${gravityDBfile}"
|
||||||
fi
|
fi
|
||||||
mv "${gravityTEMPfile}" "${gravityDBfile}"
|
mv "${gravityTEMPfile}" "${gravityDBfile}"
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
|
||||||
|
if $oldAvail; then
|
||||||
|
echo -e " ${TICK} The old database remains available."
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update timestamp when the gravity table was last updated successfully
|
# Update timestamp when the gravity table was last updated successfully
|
||||||
update_gravity_timestamp() {
|
update_gravity_timestamp() {
|
||||||
output=$( { printf ".timeout 30000\\nINSERT OR REPLACE INTO info (property,value) values ('updated',cast(strftime('%%s', 'now') as int));" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nINSERT OR REPLACE INTO info (property,value) values ('updated',cast(strftime('%%s', 'now') as int));" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -149,9 +140,9 @@ update_gravity_timestamp() {
|
|||||||
# Import domains from file and store them in the specified database table
|
# Import domains from file and store them in the specified database table
|
||||||
database_table_from_file() {
|
database_table_from_file() {
|
||||||
# Define locals
|
# Define locals
|
||||||
local table source backup_path backup_file tmpFile type
|
local table src backup_path backup_file tmpFile list_type
|
||||||
table="${1}"
|
table="${1}"
|
||||||
source="${2}"
|
src="${2}"
|
||||||
backup_path="${piholeDir}/migration_backup"
|
backup_path="${piholeDir}/migration_backup"
|
||||||
backup_file="${backup_path}/$(basename "${2}")"
|
backup_file="${backup_path}/$(basename "${2}")"
|
||||||
tmpFile="$(mktemp -p "/tmp" --suffix=".gravity")"
|
tmpFile="$(mktemp -p "/tmp" --suffix=".gravity")"
|
||||||
@@ -165,28 +156,28 @@ database_table_from_file() {
|
|||||||
|
|
||||||
# Special handling for domains to be imported into the common domainlist table
|
# Special handling for domains to be imported into the common domainlist table
|
||||||
if [[ "${table}" == "whitelist" ]]; then
|
if [[ "${table}" == "whitelist" ]]; then
|
||||||
type="0"
|
list_type="0"
|
||||||
table="domainlist"
|
table="domainlist"
|
||||||
elif [[ "${table}" == "blacklist" ]]; then
|
elif [[ "${table}" == "blacklist" ]]; then
|
||||||
type="1"
|
list_type="1"
|
||||||
table="domainlist"
|
table="domainlist"
|
||||||
elif [[ "${table}" == "regex" ]]; then
|
elif [[ "${table}" == "regex" ]]; then
|
||||||
type="3"
|
list_type="3"
|
||||||
table="domainlist"
|
table="domainlist"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get MAX(id) from domainlist when INSERTing into this table
|
# Get MAX(id) from domainlist when INSERTing into this table
|
||||||
if [[ "${table}" == "domainlist" ]]; then
|
if [[ "${table}" == "domainlist" ]]; then
|
||||||
rowid="$(sqlite3 "${gravityDBfile}" "SELECT MAX(id) FROM domainlist;")"
|
rowid="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT MAX(id) FROM domainlist;")"
|
||||||
if [[ -z "$rowid" ]]; then
|
if [[ -z "$rowid" ]]; then
|
||||||
rowid=0
|
rowid=0
|
||||||
fi
|
fi
|
||||||
rowid+=1
|
rowid+=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Loop over all domains in ${source} file
|
# Loop over all domains in ${src} file
|
||||||
# Read file line by line
|
# Read file line by line
|
||||||
grep -v '^ *#' < "${source}" | while IFS= read -r domain
|
grep -v '^ *#' < "${src}" | while IFS= read -r domain
|
||||||
do
|
do
|
||||||
# Only add non-empty lines
|
# Only add non-empty lines
|
||||||
if [[ -n "${domain}" ]]; then
|
if [[ -n "${domain}" ]]; then
|
||||||
@@ -195,10 +186,10 @@ database_table_from_file() {
|
|||||||
echo "${rowid},\"${domain}\",${timestamp}" >> "${tmpFile}"
|
echo "${rowid},\"${domain}\",${timestamp}" >> "${tmpFile}"
|
||||||
elif [[ "${table}" == "adlist" ]]; then
|
elif [[ "${table}" == "adlist" ]]; then
|
||||||
# Adlist table format
|
# Adlist table format
|
||||||
echo "${rowid},\"${domain}\",1,${timestamp},${timestamp},\"Migrated from ${source}\",,0,0,0" >> "${tmpFile}"
|
echo "${rowid},\"${domain}\",1,${timestamp},${timestamp},\"Migrated from ${src}\",,0,0,0" >> "${tmpFile}"
|
||||||
else
|
else
|
||||||
# White-, black-, and regexlist table format
|
# White-, black-, and regexlist table format
|
||||||
echo "${rowid},${type},\"${domain}\",1,${timestamp},${timestamp},\"Migrated from ${source}\"" >> "${tmpFile}"
|
echo "${rowid},${list_type},\"${domain}\",1,${timestamp},${timestamp},\"Migrated from ${src}\"" >> "${tmpFile}"
|
||||||
fi
|
fi
|
||||||
rowid+=1
|
rowid+=1
|
||||||
fi
|
fi
|
||||||
@@ -207,18 +198,18 @@ database_table_from_file() {
|
|||||||
# Store domains in database table specified by ${table}
|
# Store domains in database table specified by ${table}
|
||||||
# Use printf as .mode and .import need to be on separate lines
|
# Use printf as .mode and .import need to be on separate lines
|
||||||
# see https://unix.stackexchange.com/a/445615/83260
|
# see https://unix.stackexchange.com/a/445615/83260
|
||||||
output=$( { printf ".timeout 30000\\n.mode csv\\n.import \"%s\" %s\\n" "${tmpFile}" "${table}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\n.mode csv\\n.import \"%s\" %s\\n" "${tmpFile}" "${table}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
echo -e "\\n ${CROSS} Unable to fill table ${table}${type} in database ${gravityDBfile}\\n ${output}"
|
echo -e "\\n ${CROSS} Unable to fill table ${table}${list_type} in database ${gravityDBfile}\\n ${output}"
|
||||||
gravity_Cleanup "error"
|
gravity_Cleanup "error"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Move source file to backup directory, create directory if not existing
|
# Move source file to backup directory, create directory if not existing
|
||||||
mkdir -p "${backup_path}"
|
mkdir -p "${backup_path}"
|
||||||
mv "${source}" "${backup_file}" 2> /dev/null || \
|
mv "${src}" "${backup_file}" 2> /dev/null || \
|
||||||
echo -e " ${CROSS} Unable to backup ${source} to ${backup_path}"
|
echo -e " ${CROSS} Unable to backup ${src} to ${backup_path}"
|
||||||
|
|
||||||
# Delete tmpFile
|
# Delete tmpFile
|
||||||
rm "${tmpFile}" > /dev/null 2>&1 || \
|
rm "${tmpFile}" > /dev/null 2>&1 || \
|
||||||
@@ -227,7 +218,7 @@ database_table_from_file() {
|
|||||||
|
|
||||||
# Update timestamp of last update of this list. We store this in the "old" database as all values in the new database will later be overwritten
|
# Update timestamp of last update of this list. We store this in the "old" database as all values in the new database will later be overwritten
|
||||||
database_adlist_updated() {
|
database_adlist_updated() {
|
||||||
output=$( { printf ".timeout 30000\\nUPDATE adlist SET date_updated = (cast(strftime('%%s', 'now') as int)) WHERE id = %i;\\n" "${1}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nUPDATE adlist SET date_updated = (cast(strftime('%%s', 'now') as int)) WHERE id = %i;\\n" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -238,7 +229,7 @@ database_adlist_updated() {
|
|||||||
|
|
||||||
# Check if a column with name ${2} exists in gravity table with name ${1}
|
# Check if a column with name ${2} exists in gravity table with name ${1}
|
||||||
gravity_column_exists() {
|
gravity_column_exists() {
|
||||||
output=$( { printf ".timeout 30000\\nSELECT EXISTS(SELECT * FROM pragma_table_info('%s') WHERE name='%s');\\n" "${1}" "${2}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nSELECT EXISTS(SELECT * FROM pragma_table_info('%s') WHERE name='%s');\\n" "${1}" "${2}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
if [[ "${output}" == "1" ]]; then
|
if [[ "${output}" == "1" ]]; then
|
||||||
return 0 # Bash 0 is success
|
return 0 # Bash 0 is success
|
||||||
fi
|
fi
|
||||||
@@ -253,7 +244,7 @@ database_adlist_number() {
|
|||||||
return;
|
return;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
output=$( { printf ".timeout 30000\\nUPDATE adlist SET number = %i, invalid_domains = %i WHERE id = %i;\\n" "${num_source_lines}" "${num_invalid}" "${1}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nUPDATE adlist SET number = %i, invalid_domains = %i WHERE id = %i;\\n" "${num_source_lines}" "${num_invalid}" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -269,7 +260,7 @@ database_adlist_status() {
|
|||||||
return;
|
return;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
output=$( { printf ".timeout 30000\\nUPDATE adlist SET status = %i WHERE id = %i;\\n" "${2}" "${1}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\nUPDATE adlist SET status = %i WHERE id = %i;\\n" "${2}" "${1}" | pihole-FTL sqlite3 "${gravityDBfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -386,9 +377,9 @@ gravity_DownloadBlocklists() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Retrieve source URLs from gravity database
|
# Retrieve source URLs from gravity database
|
||||||
# We source only enabled adlists, sqlite3 stores boolean values as 0 (false) or 1 (true)
|
# We source only enabled adlists, SQLite3 stores boolean values as 0 (false) or 1 (true)
|
||||||
mapfile -t sources <<< "$(sqlite3 "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2> /dev/null)"
|
mapfile -t sources <<< "$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2> /dev/null)"
|
||||||
mapfile -t sourceIDs <<< "$(sqlite3 "${gravityDBfile}" "SELECT id FROM vw_adlist;" 2> /dev/null)"
|
mapfile -t sourceIDs <<< "$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT id FROM vw_adlist;" 2> /dev/null)"
|
||||||
|
|
||||||
# Parse source domains from $sources
|
# Parse source domains from $sources
|
||||||
mapfile -t sourceDomains <<< "$(
|
mapfile -t sourceDomains <<< "$(
|
||||||
@@ -402,14 +393,12 @@ gravity_DownloadBlocklists() {
|
|||||||
)"
|
)"
|
||||||
|
|
||||||
local str="Pulling blocklist source list into range"
|
local str="Pulling blocklist source list into range"
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
|
||||||
if [[ -n "${sources[*]}" ]] && [[ -n "${sourceDomains[*]}" ]]; then
|
if [[ -z "${sources[*]}" ]] || [[ -z "${sourceDomains[*]}" ]]; then
|
||||||
echo -e "${OVER} ${TICK} ${str}"
|
|
||||||
else
|
|
||||||
echo -e "${OVER} ${CROSS} ${str}"
|
|
||||||
echo -e " ${INFO} No source list found, or it is empty"
|
echo -e " ${INFO} No source list found, or it is empty"
|
||||||
echo ""
|
echo ""
|
||||||
return 1
|
unset sources
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local url domain agent cmd_ext str target compression
|
local url domain agent cmd_ext str target compression
|
||||||
@@ -419,7 +408,7 @@ gravity_DownloadBlocklists() {
|
|||||||
str="Preparing new gravity database"
|
str="Preparing new gravity database"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
rm "${gravityTEMPfile}" > /dev/null 2>&1
|
rm "${gravityTEMPfile}" > /dev/null 2>&1
|
||||||
output=$( { sqlite3 "${gravityTEMPfile}" < "${gravityDBschema}"; } 2>&1 )
|
output=$( { pihole-FTL sqlite3 "${gravityTEMPfile}" < "${gravityDBschema}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -477,9 +466,28 @@ gravity_DownloadBlocklists() {
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
str="Creating new gravity databases"
|
||||||
|
echo -ne " ${INFO} ${str}..."
|
||||||
|
|
||||||
|
# Gravity copying SQL script
|
||||||
|
copyGravity="$(cat "${gravityDBcopy}")"
|
||||||
|
if [[ "${gravityDBfile}" != "${gravityDBfile_default}" ]]; then
|
||||||
|
# Replace default gravity script location by custom location
|
||||||
|
copyGravity="${copyGravity//"${gravityDBfile_default}"/"${gravityDBfile}"}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
output=$( { pihole-FTL sqlite3 "${gravityTEMPfile}" <<< "${copyGravity}"; } 2>&1 )
|
||||||
|
status="$?"
|
||||||
|
|
||||||
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
|
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "${OVER} ${TICK} ${str}"
|
||||||
|
|
||||||
str="Storing downloaded domains in new gravity database"
|
str="Storing downloaded domains in new gravity database"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
output=$( { printf ".timeout 30000\\n.mode csv\\n.import \"%s\" gravity\\n" "${target}" | sqlite3 "${gravityTEMPfile}"; } 2>&1 )
|
output=$( { printf ".timeout 30000\\n.mode csv\\n.import \"%s\" gravity\\n" "${target}" | pihole-FTL sqlite3 "${gravityTEMPfile}"; } 2>&1 )
|
||||||
status="$?"
|
status="$?"
|
||||||
|
|
||||||
if [[ "${status}" -ne 0 ]]; then
|
if [[ "${status}" -ne 0 ]]; then
|
||||||
@@ -520,8 +528,9 @@ parseList() {
|
|||||||
# This sed does the following things:
|
# This sed does the following things:
|
||||||
# 1. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_)
|
# 1. Remove all domains containing invalid characters. Valid are: a-z, A-Z, 0-9, dot (.), minus (-), underscore (_)
|
||||||
# 2. Append ,adlistID to every line
|
# 2. Append ,adlistID to every line
|
||||||
# 3. Ensures there is a newline on the last line
|
# 3. Remove trailing period (see https://github.com/pi-hole/pi-hole/issues/4701)
|
||||||
sed -e "/[^a-zA-Z0-9.\_-]/d;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}"
|
# 4. Ensures there is a newline on the last line
|
||||||
|
sed -e "/[^a-zA-Z0-9.\_-]/d;s/\.$//;s/$/,${adlistID}/;/.$/a\\" "${src}" >> "${target}"
|
||||||
# Find (up to) five domains containing invalid characters (see above)
|
# Find (up to) five domains containing invalid characters (see above)
|
||||||
incorrect_lines="$(sed -e "/[^a-zA-Z0-9.\_-]/!d" "${src}" | head -n 5)"
|
incorrect_lines="$(sed -e "/[^a-zA-Z0-9.\_-]/!d" "${src}" | head -n 5)"
|
||||||
|
|
||||||
@@ -532,7 +541,7 @@ parseList() {
|
|||||||
num_target_lines_new="$(grep -c "^" "${target}")"
|
num_target_lines_new="$(grep -c "^" "${target}")"
|
||||||
# Number of new correctly added lines
|
# Number of new correctly added lines
|
||||||
num_correct_lines="$(( num_target_lines_new-num_target_lines ))"
|
num_correct_lines="$(( num_target_lines_new-num_target_lines ))"
|
||||||
# Upate number of lines in target file
|
# Update number of lines in target file
|
||||||
num_target_lines="$num_target_lines_new"
|
num_target_lines="$num_target_lines_new"
|
||||||
num_invalid="$(( num_source_lines-num_correct_lines ))"
|
num_invalid="$(( num_source_lines-num_correct_lines ))"
|
||||||
if [[ "${num_invalid}" -eq 0 ]]; then
|
if [[ "${num_invalid}" -eq 0 ]]; then
|
||||||
@@ -633,7 +642,7 @@ gravity_DownloadBlocklistFromUrl() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
httpCode=$(curl -s -L ${compression} ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${patternBuffer}" 2> /dev/null)
|
httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${patternBuffer}" 2> /dev/null)
|
||||||
|
|
||||||
case $url in
|
case $url in
|
||||||
# Did we "download" a local file?
|
# Did we "download" a local file?
|
||||||
@@ -711,10 +720,10 @@ gravity_DownloadBlocklistFromUrl() {
|
|||||||
|
|
||||||
# Parse source files into domains format
|
# Parse source files into domains format
|
||||||
gravity_ParseFileIntoDomains() {
|
gravity_ParseFileIntoDomains() {
|
||||||
local source="${1}" destination="${2}" firstLine
|
local src="${1}" destination="${2}" firstLine
|
||||||
|
|
||||||
# Determine if we are parsing a consolidated list
|
# Determine if we are parsing a consolidated list
|
||||||
#if [[ "${source}" == "${piholeDir}/${matterAndLight}" ]]; then
|
#if [[ "${src}" == "${piholeDir}/${matterAndLight}" ]]; then
|
||||||
# Remove comments and print only the domain name
|
# Remove comments and print only the domain name
|
||||||
# Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous
|
# Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous
|
||||||
# This helps with that and makes it easier to read
|
# This helps with that and makes it easier to read
|
||||||
@@ -725,7 +734,7 @@ gravity_ParseFileIntoDomains() {
|
|||||||
# 4) Remove lines containing "/"
|
# 4) Remove lines containing "/"
|
||||||
# 5) Remove leading tabs, spaces, etc.
|
# 5) Remove leading tabs, spaces, etc.
|
||||||
# 6) Delete lines not matching domain names
|
# 6) Delete lines not matching domain names
|
||||||
< "${source}" tr -d '\r' | \
|
< "${src}" tr -d '\r' | \
|
||||||
tr '[:upper:]' '[:lower:]' | \
|
tr '[:upper:]' '[:lower:]' | \
|
||||||
sed 's/\s*#.*//g' | \
|
sed 's/\s*#.*//g' | \
|
||||||
sed -r '/(\/).*$/d' | \
|
sed -r '/(\/).*$/d' | \
|
||||||
@@ -737,16 +746,16 @@ gravity_ParseFileIntoDomains() {
|
|||||||
|
|
||||||
# Individual file parsing: Keep comments, while parsing domains from each line
|
# Individual file parsing: Keep comments, while parsing domains from each line
|
||||||
# We keep comments to respect the list maintainer's licensing
|
# We keep comments to respect the list maintainer's licensing
|
||||||
read -r firstLine < "${source}"
|
read -r firstLine < "${src}"
|
||||||
|
|
||||||
# Determine how to parse individual source file formats
|
# Determine how to parse individual source file formats
|
||||||
if [[ "${firstLine,,}" =~ (adblock|ublock|^!) ]]; then
|
if [[ "${firstLine,,}" =~ (adblock|ublock|^!) ]]; then
|
||||||
# Compare $firstLine against lower case words found in Adblock lists
|
# Compare $firstLine against lower case words found in Adblock lists
|
||||||
echo -e " ${CROSS} Format: Adblock (list type not supported)"
|
echo -e " ${CROSS} Format: Adblock (list type not supported)"
|
||||||
elif grep -q "^address=/" "${source}" &> /dev/null; then
|
elif grep -q "^address=/" "${src}" &> /dev/null; then
|
||||||
# Parse Dnsmasq format lists
|
# Parse Dnsmasq format lists
|
||||||
echo -e " ${CROSS} Format: Dnsmasq (list type not supported)"
|
echo -e " ${CROSS} Format: Dnsmasq (list type not supported)"
|
||||||
elif grep -q -E "^https?://" "${source}" &> /dev/null; then
|
elif grep -q -E "^https?://" "${src}" &> /dev/null; then
|
||||||
# Parse URL list if source file contains "http://" or "https://"
|
# Parse URL list if source file contains "http://" or "https://"
|
||||||
# Scanning for "^IPv4$" is too slow with large (1M) lists on low-end hardware
|
# Scanning for "^IPv4$" is too slow with large (1M) lists on low-end hardware
|
||||||
echo -ne " ${INFO} Format: URL"
|
echo -ne " ${INFO} Format: URL"
|
||||||
@@ -762,13 +771,13 @@ gravity_ParseFileIntoDomains() {
|
|||||||
/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ { next }
|
/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ { next }
|
||||||
# Print if nonempty
|
# Print if nonempty
|
||||||
length { print }
|
length { print }
|
||||||
' "${source}" 2> /dev/null > "${destination}"
|
' "${src}" 2> /dev/null > "${destination}"
|
||||||
chmod 644 "${destination}"
|
chmod 644 "${destination}"
|
||||||
|
|
||||||
echo -e "${OVER} ${TICK} Format: URL"
|
echo -e "${OVER} ${TICK} Format: URL"
|
||||||
else
|
else
|
||||||
# Default: Keep hosts/domains file in same format as it was downloaded
|
# Default: Keep hosts/domains file in same format as it was downloaded
|
||||||
output=$( { mv "${source}" "${destination}"; } 2>&1 )
|
output=$( { mv "${src}" "${destination}"; } 2>&1 )
|
||||||
chmod 644 "${destination}"
|
chmod 644 "${destination}"
|
||||||
|
|
||||||
if [[ ! -e "${destination}" ]]; then
|
if [[ ! -e "${destination}" ]]; then
|
||||||
@@ -784,12 +793,12 @@ gravity_Table_Count() {
|
|||||||
local table="${1}"
|
local table="${1}"
|
||||||
local str="${2}"
|
local str="${2}"
|
||||||
local num
|
local num
|
||||||
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${table};")"
|
num="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${table};")"
|
||||||
if [[ "${table}" == "vw_gravity" ]]; then
|
if [[ "${table}" == "vw_gravity" ]]; then
|
||||||
local unique
|
local unique
|
||||||
unique="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(DISTINCT domain) FROM ${table};")"
|
unique="$(pihole-FTL sqlite3 "${gravityDBfile}" "SELECT COUNT(DISTINCT domain) FROM ${table};")"
|
||||||
echo -e " ${INFO} Number of ${str}: ${num} (${COL_BOLD}${unique} unique domains${COL_NC})"
|
echo -e " ${INFO} Number of ${str}: ${num} (${COL_BOLD}${unique} unique domains${COL_NC})"
|
||||||
sqlite3 "${gravityDBfile}" "INSERT OR REPLACE INTO info (property,value) VALUES ('gravity_count',${unique});"
|
pihole-FTL sqlite3 "${gravityDBfile}" "INSERT OR REPLACE INTO info (property,value) VALUES ('gravity_count',${unique});"
|
||||||
else
|
else
|
||||||
echo -e " ${INFO} Number of ${str}: ${num}"
|
echo -e " ${INFO} Number of ${str}: ${num}"
|
||||||
fi
|
fi
|
||||||
@@ -862,15 +871,19 @@ gravity_Cleanup() {
|
|||||||
|
|
||||||
database_recovery() {
|
database_recovery() {
|
||||||
local result
|
local result
|
||||||
local str="Checking integrity of existing gravity database"
|
local str="Checking integrity of existing gravity database (this can take a while)"
|
||||||
local option="${1}"
|
local option="${1}"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
if result="$(pihole-FTL sqlite3 "${gravityDBfile}" "PRAGMA integrity_check" 2>&1)"; then
|
result="$(pihole-FTL sqlite3 "${gravityDBfile}" "PRAGMA integrity_check" 2>&1)"
|
||||||
|
|
||||||
|
if [[ ${result} = "ok" ]]; then
|
||||||
echo -e "${OVER} ${TICK} ${str} - no errors found"
|
echo -e "${OVER} ${TICK} ${str} - no errors found"
|
||||||
|
|
||||||
str="Checking foreign keys of existing gravity database"
|
str="Checking foreign keys of existing gravity database (this can take a while)"
|
||||||
echo -ne " ${INFO} ${str}..."
|
echo -ne " ${INFO} ${str}..."
|
||||||
if result="$(pihole-FTL sqlite3 "${gravityDBfile}" "PRAGMA foreign_key_check" 2>&1)"; then
|
unset result
|
||||||
|
result="$(pihole-FTL sqlite3 "${gravityDBfile}" "PRAGMA foreign_key_check" 2>&1)"
|
||||||
|
if [[ -z ${result} ]]; then
|
||||||
echo -e "${OVER} ${TICK} ${str} - no errors found"
|
echo -e "${OVER} ${TICK} ${str} - no errors found"
|
||||||
if [[ "${option}" != "force" ]]; then
|
if [[ "${option}" != "force" ]]; then
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -144,7 +144,9 @@ Command line arguments can be arbitrarily combined, e.g:
|
|||||||
Start ftl in foreground with more verbose logging, process everything and shutdown immediately
|
Start ftl in foreground with more verbose logging, process everything and shutdown immediately
|
||||||
.br
|
.br
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
\fBpihole\fR(8), \fBpihole-FTL.conf\fR(5)
|
\fBpihole\fR(8)
|
||||||
|
.br
|
||||||
|
\fBFor FTL's config options please see https://docs.pi-hole.net/ftldns/configfile/\fR
|
||||||
.br
|
.br
|
||||||
.SH "COLOPHON"
|
.SH "COLOPHON"
|
||||||
|
|
||||||
|
|||||||
@@ -1,313 +0,0 @@
|
|||||||
.TH "pihole-FTL.conf" "5" "pihole-FTL.conf" "pihole-FTL.conf" "November 2020"
|
|
||||||
.SH "NAME"
|
|
||||||
|
|
||||||
pihole-FTL.conf - FTL's config file
|
|
||||||
.br
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
|
|
||||||
/etc/pihole/pihole-FTL.conf will be read by \fBpihole-FTL(8)\fR on startup.
|
|
||||||
.br
|
|
||||||
For each setting the option shown first is the default.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBBLOCKINGMODE=IP|IP-AAAA-NODATA|NODATA|NXDOMAIN|NULL\fR
|
|
||||||
.br
|
|
||||||
How should FTL reply to blocked queries?
|
|
||||||
|
|
||||||
IP - Pi-hole's IPs for blocked domains
|
|
||||||
|
|
||||||
IP-AAAA-NODATA - Pi-hole's IP + NODATA-IPv6 for blocked domains
|
|
||||||
|
|
||||||
NODATA - Using NODATA for blocked domains
|
|
||||||
|
|
||||||
NXDOMAIN - NXDOMAIN for blocked domains
|
|
||||||
|
|
||||||
NULL - Null IPs for blocked domains
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBCNAME_DEEP_INSPECT=true|false\fR
|
|
||||||
.br
|
|
||||||
Use this option to disable deep CNAME inspection. This might be beneficial for very low-end devices.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBBLOCK_ESNI=true|false\fR
|
|
||||||
.br
|
|
||||||
Block requests to _esni.* sub-domains.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBMAXLOGAGE=24.0\fR
|
|
||||||
.br
|
|
||||||
Up to how many hours of queries should be imported from the database and logs?
|
|
||||||
.br
|
|
||||||
Maximum is 744 (31 days)
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBPRIVACYLEVEL=0|1|2|3|4\fR
|
|
||||||
.br
|
|
||||||
Privacy level used to collect Pi-hole statistics.
|
|
||||||
.br
|
|
||||||
0 - show everything
|
|
||||||
.br
|
|
||||||
1 - hide domains
|
|
||||||
.br
|
|
||||||
2 - hide domains and clients
|
|
||||||
.br
|
|
||||||
3 - anonymous mode (hide everything)
|
|
||||||
.br
|
|
||||||
4 - disable all statistics
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBIGNORE_LOCALHOST=no|yes\fR
|
|
||||||
.br
|
|
||||||
Should FTL ignore queries coming from the local machine?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBAAAA_QUERY_ANALYSIS=yes|no\fR
|
|
||||||
.br
|
|
||||||
Should FTL analyze AAAA queries?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBANALYZE_ONLY_A_AND_AAAA=false|true\fR
|
|
||||||
.br
|
|
||||||
Should FTL only analyze A and AAAA queries?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBSOCKET_LISTENING=localonly|all\fR
|
|
||||||
.br
|
|
||||||
Listen only for local socket connections on the API port or permit all connections.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBFTLPORT=4711\fR
|
|
||||||
.br
|
|
||||||
On which port should FTL be listening?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBRESOLVE_IPV6=yes|no\fR
|
|
||||||
.br
|
|
||||||
Should FTL try to resolve IPv6 addresses to hostnames?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBRESOLVE_IPV4=yes|no\fR
|
|
||||||
.br
|
|
||||||
Should FTL try to resolve IPv4 addresses to hostnames?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDELAY_STARTUP=0\fR
|
|
||||||
.br
|
|
||||||
Time in seconds (between 0 and 300) to delay FTL startup.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBNICE=-10\fR
|
|
||||||
.br
|
|
||||||
Set the niceness of the Pi-hole FTL process.
|
|
||||||
.br
|
|
||||||
Can be disabled altogether by setting a value of -999.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBNAMES_FROM_NETDB=true|false\fR
|
|
||||||
.br
|
|
||||||
Control whether FTL should use a fallback option and try to obtain client names from checking the network table.
|
|
||||||
.br
|
|
||||||
E.g. IPv6 clients without a hostname will be compared via MAC address to known clients.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fB\fBREFRESH_HOSTNAMES=IPV4|ALL|NONE\fR
|
|
||||||
.br
|
|
||||||
Change how (and if) hourly PTR requests are made to check for changes in client and upstream server hostnames:
|
|
||||||
.br
|
|
||||||
IPV4 - Do the hourly PTR lookups only for IPv4 addresses resolving issues in networks with many short-lived PE IPv6 addresses.
|
|
||||||
.br
|
|
||||||
ALL - Do the hourly PTR lookups for all addresses. This can create a lot of PTR queries in networks with many IPv6 addresses.
|
|
||||||
.br
|
|
||||||
NONE - Don't do hourly PTR lookups. Look up hostnames once (when first seeing a client) and never again. Future hostname changes may be missed.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBMAXNETAGE=365\fR
|
|
||||||
.br
|
|
||||||
IP addresses (and associated host names) older than the specified number of days are removed.
|
|
||||||
.br
|
|
||||||
This avoids dead entries in the network overview table.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBEDNS0_ECS=true|false\fR
|
|
||||||
.br
|
|
||||||
Should we overwrite the query source when client information is provided through EDNS0 client subnet (ECS) information?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBPARSE_ARP_CACHE=true|false\fR
|
|
||||||
.br
|
|
||||||
Parse ARP cache to fill network overview table.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDBIMPORT=yes|no\fR
|
|
||||||
.br
|
|
||||||
Should FTL load information from the database on startup to be aware of the most recent history?
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBMAXDBDAYS=365\fR
|
|
||||||
.br
|
|
||||||
How long should queries be stored in the database? Setting this to 0 disables the database
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDBINTERVAL=1.0\fR
|
|
||||||
.br
|
|
||||||
How often do we store queries in FTL's database [minutes]?
|
|
||||||
.br
|
|
||||||
Accepts value between 0.1 (6 sec) and 1440 (1 day)
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDBFILE=/etc/pihole/pihole-FTL.db\fR
|
|
||||||
.br
|
|
||||||
Specify path and filename of FTL's SQLite long-term database.
|
|
||||||
.br
|
|
||||||
Setting this to DBFILE= disables the database altogether
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBLOGFILE=/var/log/pihole-FTL.log\fR
|
|
||||||
.br
|
|
||||||
The location of FTL's log file.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBPIDFILE=/run/pihole-FTL.pid\fR
|
|
||||||
.br
|
|
||||||
The file which contains the PID of FTL's main process.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBPORTFILE=/run/pihole-FTL.port\fR
|
|
||||||
.br
|
|
||||||
Specify path and filename where the FTL process will write its API port number.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBSOCKETFILE=/run/pihole/FTL.sock\fR
|
|
||||||
.br
|
|
||||||
The file containing the socket FTL's API is listening on.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBSETUPVARSFILE=/etc/pihole/setupVars.conf\fR
|
|
||||||
.br
|
|
||||||
The config file of Pi-hole containing, e.g., the current blocking status (do not change).
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBMACVENDORDB=/etc/pihole/macvendor.db\fR
|
|
||||||
.br
|
|
||||||
The database containing MAC -> Vendor information for the network table.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBGRAVITYDB=/etc/pihole/gravity.db\fR
|
|
||||||
.br
|
|
||||||
Specify path and filename of FTL's SQLite3 gravity database. This database contains all domains relevant for Pi-hole's DNS blocking.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_ALL=false|true\fR
|
|
||||||
.br
|
|
||||||
Enable all debug flags. If this is set to true, all other debug config options are ignored.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_DATABASE=false|true\fR
|
|
||||||
.br
|
|
||||||
Print debugging information about database actions such as SQL statements and performance.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_NETWORKING=false|true\fR
|
|
||||||
.br
|
|
||||||
Prints a list of the detected network interfaces on the startup of FTL.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_LOCKS=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about shared memory locks.
|
|
||||||
.br
|
|
||||||
Messages will be generated when waiting, obtaining, and releasing a lock.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_QUERIES=false|true\fR
|
|
||||||
.br
|
|
||||||
Print extensive DNS query information (domains, types, replies, etc.).
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_FLAGS=false|true\fR
|
|
||||||
.br
|
|
||||||
Print flags of queries received by the DNS hooks.
|
|
||||||
.br
|
|
||||||
Only effective when \fBDEBUG_QUERIES\fR is enabled as well.
|
|
||||||
|
|
||||||
\fBDEBUG_SHMEM=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about shared memory buffers.
|
|
||||||
.br
|
|
||||||
Messages are either about creating or enlarging shmem objects or string injections.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_GC=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about garbage collection (GC):
|
|
||||||
.br
|
|
||||||
What is to be removed, how many have been removed and how long did GC take.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_ARP=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about ARP table processing:
|
|
||||||
.br
|
|
||||||
How long did parsing take, whether read MAC addresses are valid, and if the macvendor.db file exists.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_REGEX=false|true\fR
|
|
||||||
.br
|
|
||||||
Controls if FTL should print extended details about regex matching.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_API=false|true\fR
|
|
||||||
.br
|
|
||||||
Print extra debugging information during telnet API calls.
|
|
||||||
.br
|
|
||||||
Currently only used to send extra information when getting all queries.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_OVERTIME=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about overTime memory operations, such as initializing or moving overTime slots.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_EXTBLOCKED=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about why FTL decided that certain queries were recognized as being externally blocked.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_CAPS=false|true\fR
|
|
||||||
.br
|
|
||||||
Print information about POSIX capabilities granted to the FTL process.
|
|
||||||
.br
|
|
||||||
The current capabilities are printed on receipt of SIGHUP i.e. after executing `killall -HUP pihole-FTL`.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_DNSMASQ_LINES=false|true\fR
|
|
||||||
.br
|
|
||||||
Print file and line causing a dnsmasq event into FTL's log files.
|
|
||||||
.br
|
|
||||||
This is handy to implement additional hooks missing from FTL.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_VECTORS=false|true\fR
|
|
||||||
.br
|
|
||||||
FTL uses dynamically allocated vectors for various tasks.
|
|
||||||
.br
|
|
||||||
This config option enables extensive debugging information such as information about allocation, referencing, deletion, and appending.
|
|
||||||
.br
|
|
||||||
|
|
||||||
\fBDEBUG_RESOLVER=false|true\fR
|
|
||||||
.br
|
|
||||||
Extensive information about hostname resolution like which DNS servers are used in the first and second hostname resolving tries.
|
|
||||||
.br
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
|
|
||||||
\fBpihole\fR(8), \fBpihole-FTL\fR(8)
|
|
||||||
.br
|
|
||||||
.SH "COLOPHON"
|
|
||||||
|
|
||||||
Pi-hole : The Faster-Than-Light (FTL) Engine is a lightweight, purpose-built daemon used to provide statistics needed for the Pi-hole Web Interface, and its API can be easily integrated into your own projects. Although it is an optional component of the Pi-hole ecosystem, it will be installed by default to provide statistics. As the name implies, FTL does its work \fIvery quickly\fR!
|
|
||||||
.br
|
|
||||||
|
|
||||||
Get sucked into the latest news and community activity by entering Pi-hole's orbit. Information about Pi-hole, and the latest version of the software can be found at https://pi-hole.net
|
|
||||||
.br
|
|
||||||
@@ -11,8 +11,6 @@ Pi-hole : A black-hole for internet advertisements
|
|||||||
.br
|
.br
|
||||||
\fBpihole -a\fR (\fB-c|-f|-k\fR)
|
\fBpihole -a\fR (\fB-c|-f|-k\fR)
|
||||||
.br
|
.br
|
||||||
\fBpihole -a -e\fR email
|
|
||||||
.br
|
|
||||||
\fBpihole -a -i\fR interface
|
\fBpihole -a -i\fR interface
|
||||||
.br
|
.br
|
||||||
\fBpihole -a -l\fR privacylevel
|
\fBpihole -a -l\fR privacylevel
|
||||||
@@ -132,9 +130,6 @@ Available commands and options:
|
|||||||
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
-f, fahrenheit Set Fahrenheit as preferred temperature unit
|
||||||
.br
|
.br
|
||||||
-k, kelvin Set Kelvin as preferred temperature unit
|
-k, kelvin Set Kelvin as preferred temperature unit
|
||||||
.br
|
|
||||||
-e, email Set an administrative contact address for the
|
|
||||||
Block Page
|
|
||||||
.br
|
.br
|
||||||
-i, interface Specify dnsmasq's interface listening behavior
|
-i, interface Specify dnsmasq's interface listening behavior
|
||||||
.br
|
.br
|
||||||
@@ -187,12 +182,12 @@ Available commands and options:
|
|||||||
|
|
||||||
(Logging options):
|
(Logging options):
|
||||||
.br
|
.br
|
||||||
on Enable the Pi-hole log at /var/log/pihole.log
|
on Enable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
.br
|
.br
|
||||||
off Disable and flush the Pi-hole log at
|
off Disable and flush the Pi-hole log at
|
||||||
/var/log/pihole.log
|
/var/log/pihole/pihole.log
|
||||||
.br
|
.br
|
||||||
off noflush Disable the Pi-hole log at /var/log/pihole.log
|
off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
.br
|
.br
|
||||||
|
|
||||||
\fB-up, updatePihole\fR [--check-only]
|
\fB-up, updatePihole\fR [--check-only]
|
||||||
|
|||||||
169
pihole
169
pihole
@@ -16,11 +16,13 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
|
|||||||
# error due to modifying a readonly variable.
|
# error due to modifying a readonly variable.
|
||||||
setupVars="/etc/pihole/setupVars.conf"
|
setupVars="/etc/pihole/setupVars.conf"
|
||||||
PI_HOLE_BIN_DIR="/usr/local/bin"
|
PI_HOLE_BIN_DIR="/usr/local/bin"
|
||||||
readonly FTL_PID_FILE="/run/pihole-FTL.pid"
|
|
||||||
|
|
||||||
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
|
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
|
||||||
source "${colfile}"
|
source "${colfile}"
|
||||||
|
|
||||||
|
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
|
||||||
|
source "${utilsfile}"
|
||||||
|
|
||||||
webpageFunc() {
|
webpageFunc() {
|
||||||
source "${PI_HOLE_SCRIPT_DIR}/webpage.sh"
|
source "${PI_HOLE_SCRIPT_DIR}/webpage.sh"
|
||||||
main "$@"
|
main "$@"
|
||||||
@@ -33,19 +35,20 @@ listFunc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugFunc() {
|
debugFunc() {
|
||||||
local automated
|
local automated
|
||||||
local web
|
local web
|
||||||
|
local check_database_integrity
|
||||||
|
# Pull off the `debug` leaving passed call augmentation flags in $1
|
||||||
|
shift
|
||||||
|
|
||||||
# Pull off the `debug` leaving passed call augmentation flags in $1
|
for value in "$@"; do
|
||||||
shift
|
[[ "$value" == *"-a"* ]] && automated="true"
|
||||||
if [[ "$@" == *"-a"* ]]; then
|
[[ "$value" == *"-w"* ]] && web="true"
|
||||||
automated="true"
|
[[ "$value" == *"-c"* ]] && check_database_integrity="true"
|
||||||
fi
|
[[ "$value" == *"--check_database"* ]] && check_database_integrity="true"
|
||||||
if [[ "$@" == *"-w"* ]]; then
|
done
|
||||||
web="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AUTOMATED=${automated:-} WEBCALL=${web:-} "${PI_HOLE_SCRIPT_DIR}"/piholeDebug.sh
|
AUTOMATED=${automated:-} WEBCALL=${web:-} CHECK_DATABASE=${check_database_integrity:-} "${PI_HOLE_SCRIPT_DIR}"/piholeDebug.sh
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,34 +100,21 @@ versionFunc() {
|
|||||||
exec "${PI_HOLE_SCRIPT_DIR}"/version.sh "$@"
|
exec "${PI_HOLE_SCRIPT_DIR}"/version.sh "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get PID of main pihole-FTL process
|
|
||||||
getFTLPID() {
|
|
||||||
local pid
|
|
||||||
|
|
||||||
if [ -s "${FTL_PID_FILE}" ]; then
|
|
||||||
# -s: FILE exists and has a size greater than zero
|
|
||||||
pid="$(<"$FTL_PID_FILE")"
|
|
||||||
# Exploit prevention: unset the variable if there is malicious content
|
|
||||||
# Verify that the value read from the file is numeric
|
|
||||||
[[ "$pid" =~ [^[:digit:]] ]] && unset pid
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If FTL is not running, or the PID file contains malicious stuff, substitute
|
|
||||||
# negative PID to signal this to the caller
|
|
||||||
echo "${pid:=-1}"
|
|
||||||
}
|
|
||||||
|
|
||||||
restartDNS() {
|
restartDNS() {
|
||||||
local svcOption svc str output status pid icon
|
local svcOption svc str output status pid icon FTL_PID_FILE
|
||||||
svcOption="${1:-restart}"
|
svcOption="${1:-restart}"
|
||||||
|
|
||||||
|
# get the current path to the pihole-FTL.pid
|
||||||
|
FTL_PID_FILE="$(getFTLPIDFile)"
|
||||||
|
|
||||||
# Determine if we should reload or restart
|
# Determine if we should reload or restart
|
||||||
if [[ "${svcOption}" =~ "reload-lists" ]]; then
|
if [[ "${svcOption}" =~ "reload-lists" ]]; then
|
||||||
# Reloading of the lists has been requested
|
# Reloading of the lists has been requested
|
||||||
# Note 1: This will NOT re-read any *.conf files
|
# Note 1: This will NOT re-read any *.conf files
|
||||||
# Note 2: We cannot use killall here as it does
|
# Note 2: We cannot use killall here as it does
|
||||||
# not know about real-time signals
|
# not know about real-time signals
|
||||||
pid="$(getFTLPID)"
|
|
||||||
|
pid="$(getFTLPID ${FTL_PID_FILE})"
|
||||||
if [[ "$pid" -eq "-1" ]]; then
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
svc="true"
|
svc="true"
|
||||||
str="FTL is not running"
|
str="FTL is not running"
|
||||||
@@ -137,7 +127,7 @@ restartDNS() {
|
|||||||
elif [[ "${svcOption}" =~ "reload" ]]; then
|
elif [[ "${svcOption}" =~ "reload" ]]; then
|
||||||
# Reloading of the DNS cache has been requested
|
# Reloading of the DNS cache has been requested
|
||||||
# Note: This will NOT re-read any *.conf files
|
# Note: This will NOT re-read any *.conf files
|
||||||
pid="$(getFTLPID)"
|
pid="$(getFTLPID ${FTL_PID_FILE})"
|
||||||
if [[ "$pid" -eq "-1" ]]; then
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
svc="true"
|
svc="true"
|
||||||
str="FTL is not running"
|
str="FTL is not running"
|
||||||
@@ -223,8 +213,7 @@ Time:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local str="Pi-hole Disabled"
|
local str="Pi-hole Disabled"
|
||||||
sed -i "/BLOCKING_ENABLED=/d" "${setupVars}"
|
addOrEditKeyValPair "${setupVars}" "BLOCKING_ENABLED" "false"
|
||||||
echo "BLOCKING_ENABLED=false" >> "${setupVars}"
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Enable Pi-hole
|
# Enable Pi-hole
|
||||||
@@ -236,8 +225,7 @@ Time:
|
|||||||
echo -e " ${INFO} Enabling blocking"
|
echo -e " ${INFO} Enabling blocking"
|
||||||
local str="Pi-hole Enabled"
|
local str="Pi-hole Enabled"
|
||||||
|
|
||||||
sed -i "/BLOCKING_ENABLED=/d" "${setupVars}"
|
addOrEditKeyValPair "${setupVars}" "BLOCKING_ENABLED" "true"
|
||||||
echo "BLOCKING_ENABLED=true" >> "${setupVars}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
restartDNS reload-lists
|
restartDNS reload-lists
|
||||||
@@ -253,14 +241,14 @@ Example: 'pihole logging on'
|
|||||||
Specify whether the Pi-hole log should be used
|
Specify whether the Pi-hole log should be used
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
on Enable the Pi-hole log at /var/log/pihole.log
|
on Enable the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
off Disable and flush the Pi-hole log at /var/log/pihole.log
|
off Disable and flush the Pi-hole log at /var/log/pihole/pihole.log
|
||||||
off noflush Disable the Pi-hole log at /var/log/pihole.log"
|
off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log"
|
||||||
exit 0
|
exit 0
|
||||||
elif [[ "${1}" == "off" ]]; then
|
elif [[ "${1}" == "off" ]]; then
|
||||||
# Disable logging
|
# Disable logging
|
||||||
sed -i 's/^log-queries/#log-queries/' /etc/dnsmasq.d/01-pihole.conf
|
removeKey /etc/dnsmasq.d/01-pihole.conf "log-queries"
|
||||||
sed -i 's/^QUERY_LOGGING=true/QUERY_LOGGING=false/' /etc/pihole/setupVars.conf
|
addOrEditKeyValPair "${setupVars}" "QUERY_LOGGING" "false"
|
||||||
if [[ "${2}" != "noflush" ]]; then
|
if [[ "${2}" != "noflush" ]]; then
|
||||||
# Flush logs
|
# Flush logs
|
||||||
"${PI_HOLE_BIN_DIR}"/pihole -f
|
"${PI_HOLE_BIN_DIR}"/pihole -f
|
||||||
@@ -269,8 +257,8 @@ Options:
|
|||||||
local str="Logging has been disabled!"
|
local str="Logging has been disabled!"
|
||||||
elif [[ "${1}" == "on" ]]; then
|
elif [[ "${1}" == "on" ]]; then
|
||||||
# Enable logging
|
# Enable logging
|
||||||
sed -i 's/^#log-queries/log-queries/' /etc/dnsmasq.d/01-pihole.conf
|
addKey /etc/dnsmasq.d/01-pihole.conf "log-queries"
|
||||||
sed -i 's/^QUERY_LOGGING=false/QUERY_LOGGING=true/' /etc/pihole/setupVars.conf
|
addOrEditKeyValPair "${setupVars}" "QUERY_LOGGING" "true"
|
||||||
echo -e " ${INFO} Enabling logging..."
|
echo -e " ${INFO} Enabling logging..."
|
||||||
local str="Logging has been enabled!"
|
local str="Logging has been enabled!"
|
||||||
else
|
else
|
||||||
@@ -314,32 +302,36 @@ analyze_ports() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statusFunc() {
|
statusFunc() {
|
||||||
# Determine if there is pihole-FTL service is listening
|
# Determine if there is pihole-FTL service is listening
|
||||||
local listening pid port
|
local pid port ftl_api_port ftl_pid_file
|
||||||
|
|
||||||
pid="$(getFTLPID)"
|
ftl_pid_file="$(getFTLPIDFile)"
|
||||||
if [[ "$pid" -eq "-1" ]]; then
|
|
||||||
case "${1}" in
|
pid="$(getFTLPID ${ftl_pid_file})"
|
||||||
"web") echo "-1";;
|
|
||||||
*) echo -e " ${CROSS} DNS service is NOT running";;
|
ftl_api_port="$(getFTLAPIPort)"
|
||||||
esac
|
if [[ "$pid" -eq "-1" ]]; then
|
||||||
return 0
|
case "${1}" in
|
||||||
else
|
"web") echo "-1";;
|
||||||
#get the port pihole-FTL is listening on by using FTL's telnet API
|
*) echo -e " ${CROSS} DNS service is NOT running";;
|
||||||
port="$(echo ">dns-port >quit" | nc 127.0.0.1 4711)"
|
esac
|
||||||
if [[ "${port}" == "0" ]]; then
|
return 0
|
||||||
case "${1}" in
|
|
||||||
"web") echo "-1";;
|
|
||||||
*) echo -e " ${CROSS} DNS service is NOT listening";;
|
|
||||||
esac
|
|
||||||
return 0
|
|
||||||
else
|
else
|
||||||
if [[ "${1}" != "web" ]]; then
|
#get the DNS port pihole-FTL is listening on by using FTL's telnet API
|
||||||
echo -e " ${TICK} FTL is listening on port ${port}"
|
port="$(echo ">dns-port >quit" | nc 127.0.0.1 "$ftl_api_port")"
|
||||||
analyze_ports "${port}"
|
if [[ "${port}" == "0" ]]; then
|
||||||
fi
|
case "${1}" in
|
||||||
|
"web") echo "-1";;
|
||||||
|
*) echo -e " ${CROSS} DNS service is NOT listening";;
|
||||||
|
esac
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
if [[ "${1}" != "web" ]]; then
|
||||||
|
echo -e " ${TICK} FTL is listening on port ${port}"
|
||||||
|
analyze_ports "${port}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Determine if Pi-hole's blocking is enabled
|
# Determine if Pi-hole's blocking is enabled
|
||||||
if grep -q "BLOCKING_ENABLED=false" /etc/pihole/setupVars.conf; then
|
if grep -q "BLOCKING_ENABLED=false" /etc/pihole/setupVars.conf; then
|
||||||
@@ -363,7 +355,7 @@ statusFunc() {
|
|||||||
# Enable blocking
|
# Enable blocking
|
||||||
"${PI_HOLE_BIN_DIR}"/pihole enable
|
"${PI_HOLE_BIN_DIR}"/pihole enable
|
||||||
fi
|
fi
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
tailFunc() {
|
tailFunc() {
|
||||||
@@ -380,7 +372,7 @@ tailFunc() {
|
|||||||
# Color blocklist/blacklist/wildcard entries as red
|
# Color blocklist/blacklist/wildcard entries as red
|
||||||
# Color A/AAAA/DHCP strings as white
|
# Color A/AAAA/DHCP strings as white
|
||||||
# Color everything else as gray
|
# Color everything else as gray
|
||||||
tail -f /var/log/pihole.log | grep --line-buffered "${1}" | sed -E \
|
tail -f /var/log/pihole/pihole.log | grep --line-buffered "${1}" | sed -E \
|
||||||
-e "s,($(date +'%b %d ')| dnsmasq\[[0-9]*\]),,g" \
|
-e "s,($(date +'%b %d ')| dnsmasq\[[0-9]*\]),,g" \
|
||||||
-e "s,(.*(blacklisted |gravity blocked ).*),${COL_RED}&${COL_NC}," \
|
-e "s,(.*(blacklisted |gravity blocked ).*),${COL_RED}&${COL_NC}," \
|
||||||
-e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \
|
-e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \
|
||||||
@@ -453,6 +445,7 @@ Whitelist/Blacklist Options:
|
|||||||
|
|
||||||
Debugging Options:
|
Debugging Options:
|
||||||
-d, debug Start a debugging session
|
-d, debug Start a debugging session
|
||||||
|
Add '-c' or '--check-database' to include a Pi-hole database integrity check
|
||||||
Add '-a' to automatically upload the log to tricorder.pi-hole.net
|
Add '-a' to automatically upload the log to tricorder.pi-hole.net
|
||||||
-f, flush Flush the Pi-hole log
|
-f, flush Flush the Pi-hole log
|
||||||
-r, reconfigure Reconfigure or Repair Pi-hole subsystems
|
-r, reconfigure Reconfigure or Repair Pi-hole subsystems
|
||||||
@@ -494,8 +487,39 @@ if [[ $# = 0 ]]; then
|
|||||||
helpFunc
|
helpFunc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# functions that do not require sudo power
|
||||||
case "${1}" in
|
case "${1}" in
|
||||||
"-h" | "help" | "--help" ) helpFunc;;
|
"-h" | "help" | "--help" ) helpFunc;;
|
||||||
|
"-v" | "version" ) versionFunc "$@";;
|
||||||
|
"-c" | "chronometer" ) chronometerFunc "$@";;
|
||||||
|
"-q" | "query" ) queryFunc "$@";;
|
||||||
|
"status" ) statusFunc "$2";;
|
||||||
|
|
||||||
|
"tricorder" ) tricorderFunc;;
|
||||||
|
|
||||||
|
# we need to add all arguments that require sudo power to not trigger the * argument
|
||||||
|
"-w" | "whitelist" ) ;;
|
||||||
|
"-b" | "blacklist" ) ;;
|
||||||
|
"--wild" | "wildcard" ) ;;
|
||||||
|
"--regex" | "regex" ) ;;
|
||||||
|
"--white-regex" | "white-regex" ) ;;
|
||||||
|
"--white-wild" | "white-wild" ) ;;
|
||||||
|
"-f" | "flush" ) ;;
|
||||||
|
"-up" | "updatePihole" ) ;;
|
||||||
|
"-r" | "reconfigure" ) ;;
|
||||||
|
"-g" | "updateGravity" ) ;;
|
||||||
|
"-l" | "logging" ) ;;
|
||||||
|
"uninstall" ) ;;
|
||||||
|
"enable" ) ;;
|
||||||
|
"disable" ) ;;
|
||||||
|
"-d" | "debug" ) ;;
|
||||||
|
"restartdns" ) ;;
|
||||||
|
"-a" | "admin" ) ;;
|
||||||
|
"checkout" ) ;;
|
||||||
|
"updatechecker" ) ;;
|
||||||
|
"arpflush" ) ;;
|
||||||
|
"-t" | "tail" ) ;;
|
||||||
|
* ) helpFunc;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Must be root to use this tool
|
# Must be root to use this tool
|
||||||
@@ -522,21 +546,14 @@ case "${1}" in
|
|||||||
"-up" | "updatePihole" ) updatePiholeFunc "$@";;
|
"-up" | "updatePihole" ) updatePiholeFunc "$@";;
|
||||||
"-r" | "reconfigure" ) reconfigurePiholeFunc;;
|
"-r" | "reconfigure" ) reconfigurePiholeFunc;;
|
||||||
"-g" | "updateGravity" ) updateGravityFunc "$@";;
|
"-g" | "updateGravity" ) updateGravityFunc "$@";;
|
||||||
"-c" | "chronometer" ) chronometerFunc "$@";;
|
|
||||||
"-h" | "help" ) helpFunc;;
|
|
||||||
"-v" | "version" ) versionFunc "$@";;
|
|
||||||
"-q" | "query" ) queryFunc "$@";;
|
|
||||||
"-l" | "logging" ) piholeLogging "$@";;
|
"-l" | "logging" ) piholeLogging "$@";;
|
||||||
"uninstall" ) uninstallFunc;;
|
"uninstall" ) uninstallFunc;;
|
||||||
"enable" ) piholeEnable 1;;
|
"enable" ) piholeEnable 1;;
|
||||||
"disable" ) piholeEnable 0 "$2";;
|
"disable" ) piholeEnable 0 "$2";;
|
||||||
"status" ) statusFunc "$2";;
|
|
||||||
"restartdns" ) restartDNS "$2";;
|
"restartdns" ) restartDNS "$2";;
|
||||||
"-a" | "admin" ) webpageFunc "$@";;
|
"-a" | "admin" ) webpageFunc "$@";;
|
||||||
"-t" | "tail" ) tailFunc "$2";;
|
|
||||||
"checkout" ) piholeCheckoutFunc "$@";;
|
"checkout" ) piholeCheckoutFunc "$@";;
|
||||||
"tricorder" ) tricorderFunc;;
|
|
||||||
"updatechecker" ) updateCheckFunc "$@";;
|
"updatechecker" ) updateCheckFunc "$@";;
|
||||||
"arpflush" ) arpFunc "$@";;
|
"arpflush" ) arpFunc "$@";;
|
||||||
* ) helpFunc;;
|
"-t" | "tail" ) tailFunc "$2";;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
FROM centos:8
|
FROM quay.io/centos/centos:stream8
|
||||||
RUN yum install -y git
|
RUN yum install -y git initscripts
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
ENV GITDIR /etc/.pihole
|
||||||
ENV SCRIPTDIR /opt/pihole
|
ENV SCRIPTDIR /opt/pihole
|
||||||
@@ -12,7 +12,7 @@ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
FROM buildpack-deps:stretch-scm
|
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
|
||||||
ENV SCRIPTDIR /opt/pihole
|
|
||||||
|
|
||||||
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
|
||||||
ADD . $GITDIR
|
|
||||||
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
|
||||||
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|
||||||
|
|
||||||
RUN true && \
|
|
||||||
chmod +x $SCRIPTDIR/*
|
|
||||||
|
|
||||||
ENV PH_TEST true
|
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
FROM fedora:33
|
|
||||||
RUN dnf install -y git
|
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
|
||||||
ENV SCRIPTDIR /opt/pihole
|
|
||||||
|
|
||||||
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
|
||||||
ADD . $GITDIR
|
|
||||||
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
|
||||||
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|
||||||
|
|
||||||
RUN true && \
|
|
||||||
chmod +x $SCRIPTDIR/*
|
|
||||||
|
|
||||||
ENV PH_TEST true
|
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
FROM fedora:34
|
FROM fedora:35
|
||||||
RUN dnf install -y git
|
RUN dnf install -y git initscripts
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
ENV GITDIR /etc/.pihole
|
||||||
ENV SCRIPTDIR /opt/pihole
|
ENV SCRIPTDIR /opt/pihole
|
||||||
@@ -12,7 +12,7 @@ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
FROM centos:7
|
FROM fedora:36
|
||||||
RUN yum install -y git
|
RUN dnf install -y git initscripts
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
ENV GITDIR /etc/.pihole
|
||||||
ENV SCRIPTDIR /opt/pihole
|
ENV SCRIPTDIR /opt/pihole
|
||||||
@@ -12,7 +12,7 @@ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
FROM buildpack-deps:xenial-scm
|
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
|
||||||
ENV SCRIPTDIR /opt/pihole
|
|
||||||
|
|
||||||
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
|
||||||
ADD . $GITDIR
|
|
||||||
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
|
||||||
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|
||||||
|
|
||||||
RUN true && \
|
|
||||||
chmod +x $SCRIPTDIR/*
|
|
||||||
|
|
||||||
ENV PH_TEST true
|
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
FROM buildpack-deps:bionic-scm
|
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
|
||||||
ENV SCRIPTDIR /opt/pihole
|
|
||||||
|
|
||||||
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
|
|
||||||
ADD . $GITDIR
|
|
||||||
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/
|
|
||||||
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
|
|
||||||
|
|
||||||
RUN true && \
|
|
||||||
chmod +x $SCRIPTDIR/*
|
|
||||||
|
|
||||||
ENV PH_TEST true
|
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
|
||||||
@@ -12,7 +12,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM buildpack-deps:hirsute-scm
|
FROM buildpack-deps:jammy-scm
|
||||||
|
|
||||||
ENV GITDIR /etc/.pihole
|
ENV GITDIR /etc/.pihole
|
||||||
ENV SCRIPTDIR /opt/pihole
|
ENV SCRIPTDIR /opt/pihole
|
||||||
@@ -12,7 +12,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|||||||
RUN true && \
|
RUN true && \
|
||||||
chmod +x $SCRIPTDIR/*
|
chmod +x $SCRIPTDIR/*
|
||||||
|
|
||||||
ENV PH_TEST true
|
ENV SKIP_INSTALL true
|
||||||
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
ENV OS_CHECK_DOMAIN_NAME dev-supportedos.pi-hole.net
|
||||||
|
|
||||||
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \
|
||||||
179
test/conftest.py
179
test/conftest.py
@@ -6,12 +6,12 @@ from textwrap import dedent
|
|||||||
|
|
||||||
|
|
||||||
SETUPVARS = {
|
SETUPVARS = {
|
||||||
'PIHOLE_INTERFACE': 'eth99',
|
"PIHOLE_INTERFACE": "eth99",
|
||||||
'PIHOLE_DNS_1': '4.2.2.1',
|
"PIHOLE_DNS_1": "4.2.2.1",
|
||||||
'PIHOLE_DNS_2': '4.2.2.2'
|
"PIHOLE_DNS_2": "4.2.2.2",
|
||||||
}
|
}
|
||||||
|
|
||||||
IMAGE = 'pytest_pihole:test_container'
|
IMAGE = "pytest_pihole:test_container"
|
||||||
|
|
||||||
tick_box = "[\x1b[1;32m\u2713\x1b[0m]"
|
tick_box = "[\x1b[1;32m\u2713\x1b[0m]"
|
||||||
cross_box = "[\x1b[1;31m\u2717\x1b[0m]"
|
cross_box = "[\x1b[1;31m\u2717\x1b[0m]"
|
||||||
@@ -38,132 +38,187 @@ testinfra.backend.docker.DockerBackend.run = run_bash
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def host():
|
def host():
|
||||||
# run a container
|
# run a container
|
||||||
docker_id = subprocess.check_output(
|
docker_id = (
|
||||||
['docker', 'run', '-t', '-d', '--cap-add=ALL', IMAGE]).decode().strip()
|
subprocess.check_output(["docker", "run", "-t", "-d", "--cap-add=ALL", IMAGE])
|
||||||
|
.decode()
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
|
||||||
# return a testinfra connection to the container
|
# return a testinfra connection to the container
|
||||||
docker_host = testinfra.get_host("docker://" + docker_id)
|
docker_host = testinfra.get_host("docker://" + docker_id)
|
||||||
|
|
||||||
yield docker_host
|
yield docker_host
|
||||||
# at the end of the test suite, destroy the container
|
# at the end of the test suite, destroy the container
|
||||||
subprocess.check_call(['docker', 'rm', '-f', docker_id])
|
subprocess.check_call(["docker", "rm", "-f", docker_id])
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
def mock_command(script, args, container):
|
def mock_command(script, args, container):
|
||||||
'''
|
"""
|
||||||
Allows for setup of commands we don't really want to have to run for real
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
in unit tests
|
in unit tests
|
||||||
'''
|
"""
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
mock_script = dedent(r'''\
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1" in'''.format(script=script))
|
case "\$1" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
for k, v in args.items():
|
for k, v in args.items():
|
||||||
case = dedent('''
|
case = dedent(
|
||||||
|
"""
|
||||||
{arg})
|
{arg})
|
||||||
echo {res}
|
echo {res}
|
||||||
exit {retcode}
|
exit {retcode}
|
||||||
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
mock_script += case
|
mock_script += case
|
||||||
mock_script += dedent('''
|
mock_script += dedent(
|
||||||
esac''')
|
"""
|
||||||
container.run('''
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
cat <<EOF> {script}\n{content}\nEOF
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
chmod +x {script}
|
chmod +x {script}
|
||||||
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
content=mock_script,
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
scriptlog=script))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def mock_command_passthrough(script, args, container):
|
def mock_command_passthrough(script, args, container):
|
||||||
'''
|
"""
|
||||||
Per other mock_command* functions, allows intercepting of commands we don't want to run for real
|
Per other mock_command* functions, allows intercepting of commands we don't want to run for real
|
||||||
in unit tests, however also allows only specific arguments to be mocked. Anything not defined will
|
in unit tests, however also allows only specific arguments to be mocked. Anything not defined will
|
||||||
be passed through to the actual command.
|
be passed through to the actual command.
|
||||||
|
|
||||||
Example use-case: mocking `git pull` but still allowing `git clone` to work as intended
|
Example use-case: mocking `git pull` but still allowing `git clone` to work as intended
|
||||||
'''
|
"""
|
||||||
orig_script_path = container.check_output('command -v {}'.format(script))
|
orig_script_path = container.check_output("command -v {}".format(script))
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
mock_script = dedent(r'''\
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1" in'''.format(script=script))
|
case "\$1" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
for k, v in args.items():
|
for k, v in args.items():
|
||||||
case = dedent('''
|
case = dedent(
|
||||||
|
"""
|
||||||
{arg})
|
{arg})
|
||||||
echo {res}
|
echo {res}
|
||||||
exit {retcode}
|
exit {retcode}
|
||||||
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
mock_script += case
|
mock_script += case
|
||||||
mock_script += dedent(r'''
|
mock_script += dedent(
|
||||||
|
r"""
|
||||||
*)
|
*)
|
||||||
{orig_script_path} "\$@"
|
{orig_script_path} "\$@"
|
||||||
;;'''.format(orig_script_path=orig_script_path))
|
;;""".format(
|
||||||
mock_script += dedent('''
|
orig_script_path=orig_script_path
|
||||||
esac''')
|
)
|
||||||
container.run('''
|
)
|
||||||
|
mock_script += dedent(
|
||||||
|
"""
|
||||||
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
cat <<EOF> {script}\n{content}\nEOF
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
chmod +x {script}
|
chmod +x {script}
|
||||||
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
content=mock_script,
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
scriptlog=script))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def mock_command_run(script, args, container):
|
def mock_command_run(script, args, container):
|
||||||
'''
|
"""
|
||||||
Allows for setup of commands we don't really want to have to run for real
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
in unit tests
|
in unit tests
|
||||||
'''
|
"""
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
mock_script = dedent(r'''\
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1 \$2" in'''.format(script=script))
|
case "\$1 \$2" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
for k, v in args.items():
|
for k, v in args.items():
|
||||||
case = dedent('''
|
case = dedent(
|
||||||
|
"""
|
||||||
\"{arg}\")
|
\"{arg}\")
|
||||||
echo {res}
|
echo {res}
|
||||||
exit {retcode}
|
exit {retcode}
|
||||||
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
mock_script += case
|
mock_script += case
|
||||||
mock_script += dedent('''
|
mock_script += dedent(
|
||||||
esac''')
|
"""
|
||||||
container.run('''
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
cat <<EOF> {script}\n{content}\nEOF
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
chmod +x {script}
|
chmod +x {script}
|
||||||
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
content=mock_script,
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
scriptlog=script))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def mock_command_2(script, args, container):
|
def mock_command_2(script, args, container):
|
||||||
'''
|
"""
|
||||||
Allows for setup of commands we don't really want to have to run for real
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
in unit tests
|
in unit tests
|
||||||
'''
|
"""
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = "/usr/local/bin/{}".format(script)
|
||||||
mock_script = dedent(r'''\
|
mock_script = dedent(
|
||||||
|
r"""\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1 \$2" in'''.format(script=script))
|
case "\$1 \$2" in""".format(
|
||||||
|
script=script
|
||||||
|
)
|
||||||
|
)
|
||||||
for k, v in args.items():
|
for k, v in args.items():
|
||||||
case = dedent('''
|
case = dedent(
|
||||||
|
"""
|
||||||
\"{arg}\")
|
\"{arg}\")
|
||||||
echo \"{res}\"
|
echo \"{res}\"
|
||||||
exit {retcode}
|
exit {retcode}
|
||||||
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
;;""".format(
|
||||||
|
arg=k, res=v[0], retcode=v[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
mock_script += case
|
mock_script += case
|
||||||
mock_script += dedent('''
|
mock_script += dedent(
|
||||||
esac''')
|
"""
|
||||||
container.run('''
|
esac"""
|
||||||
|
)
|
||||||
|
container.run(
|
||||||
|
"""
|
||||||
cat <<EOF> {script}\n{content}\nEOF
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
chmod +x {script}
|
chmod +x {script}
|
||||||
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
rm -f /var/log/{scriptlog}""".format(
|
||||||
content=mock_script,
|
script=full_script_path, content=mock_script, scriptlog=script
|
||||||
scriptlog=script))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_script(Pihole, script):
|
def run_script(Pihole, script):
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
docker-compose
|
docker-compose
|
||||||
pytest
|
pytest
|
||||||
pytest-xdist
|
pytest-xdist
|
||||||
pytest-cov
|
|
||||||
pytest-testinfra
|
pytest-testinfra
|
||||||
tox
|
tox
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
setup_requires=['pytest-runner'],
|
py_modules=[],
|
||||||
tests_require=['pytest'],
|
setup_requires=["pytest-runner"],
|
||||||
|
tests_require=["pytest"],
|
||||||
)
|
)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
152
test/test_any_utils.py
Normal file
152
test/test_any_utils.py
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
def test_key_val_replacement_works(host):
|
||||||
|
"""Confirms addOrEditKeyValPair either adds or replaces a key value pair in a given file"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value3"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_FOUR" "value4"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
cat ./testoutput
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "KEY_ONE=value3\nKEY_TWO=value2\nKEY_FOUR=value4\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_key_addition_works(host):
|
||||||
|
"""Confirms addKey adds a key (no value) to a file without duplicating it"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
addKey "./testoutput" "KEY_ONE"
|
||||||
|
addKey "./testoutput" "KEY_ONE"
|
||||||
|
addKey "./testoutput" "KEY_TWO"
|
||||||
|
addKey "./testoutput" "KEY_TWO"
|
||||||
|
addKey "./testoutput" "KEY_THREE"
|
||||||
|
addKey "./testoutput" "KEY_THREE"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
cat ./testoutput
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "KEY_ONE\nKEY_TWO\nKEY_THREE\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_key_removal_works(host):
|
||||||
|
"""Confirms removeKey removes a key or key/value pair"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2"
|
||||||
|
addOrEditKeyValPair "./testoutput" "KEY_THREE" "value3"
|
||||||
|
addKey "./testoutput" "KEY_FOUR"
|
||||||
|
removeKey "./testoutput" "KEY_TWO"
|
||||||
|
removeKey "./testoutput" "KEY_FOUR"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
cat ./testoutput
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "KEY_ONE=value1\nKEY_THREE=value3\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLAPIPort_default(host):
|
||||||
|
"""Confirms getFTLAPIPort returns the default API port"""
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLAPIPort
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "4711\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLAPIPort_custom(host):
|
||||||
|
"""Confirms getFTLAPIPort returns a custom API port"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
echo "FTLPORT=1234" > /etc/pihole/pihole-FTL.conf
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLAPIPort
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "1234\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLAPIPort_malicious(host):
|
||||||
|
"""Confirms getFTLAPIPort returns 4711 if the setting in pihole-FTL.conf contains non-digits"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
echo "FTLPORT=*$ssdfsd" > /etc/pihole/pihole-FTL.conf
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLAPIPort
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "4711\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLPIDFile_default(host):
|
||||||
|
"""Confirms getFTLPIDFile returns the default PID file path"""
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLPIDFile
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "/run/pihole-FTL.pid\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLPID_default(host):
|
||||||
|
"""Confirms getFTLPID returns the default value if FTL is not running"""
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
getFTLPID
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "-1\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_getFTLPIDFile_and_getFTLPID_custom(host):
|
||||||
|
"""Confirms getFTLPIDFile returns a custom PID file path"""
|
||||||
|
host.run(
|
||||||
|
"""
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
echo "PIDFILE=${tmpfile}" > /etc/pihole/pihole-FTL.conf
|
||||||
|
echo "1234" > ${tmpfile}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
output = host.run(
|
||||||
|
"""
|
||||||
|
source /opt/pihole/utils.sh
|
||||||
|
FTL_PID_FILE=$(getFTLPIDFile)
|
||||||
|
getFTLPID "${FTL_PID_FILE}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
expected_stdout = "1234\n"
|
||||||
|
assert expected_stdout == output.stdout
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
from .conftest import (
|
|
||||||
tick_box,
|
|
||||||
info_box,
|
|
||||||
mock_command,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_default_optout_centos_eq_7(host):
|
|
||||||
'''
|
|
||||||
confirms the default behavior to opt-out of installing PHP7 from REMI
|
|
||||||
'''
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
expected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS. '
|
|
||||||
'Deprecated PHP may be in use.')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_user_optout_centos_eq_7(host):
|
|
||||||
'''
|
|
||||||
confirms installer behavior when user opt-out of installing PHP7 from REMI
|
|
||||||
(php not currently installed)
|
|
||||||
'''
|
|
||||||
# Whiptail dialog returns Cancel for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '1')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
expected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS. '
|
|
||||||
'Deprecated PHP may be in use.')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_user_optin_centos_eq_7(host):
|
|
||||||
'''
|
|
||||||
confirms installer behavior when user opt-in to installing PHP7 from REMI
|
|
||||||
(php not currently installed)
|
|
||||||
'''
|
|
||||||
# Whiptail dialog returns Continue for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '0')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
assert 'opt-out' not in package_manager_detect.stdout
|
|
||||||
expected_stdout = info_box + (' Enabling Remi\'s RPM repository '
|
|
||||||
'(https://rpms.remirepo.net)')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
expected_stdout = tick_box + (' Remi\'s RPM repository has '
|
|
||||||
'been enabled for PHP7')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert remi_package.is_installed
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
from .conftest import (
|
|
||||||
tick_box,
|
|
||||||
info_box,
|
|
||||||
mock_command,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_default_continue_centos_gte_8(host):
|
|
||||||
'''
|
|
||||||
confirms the latest version of CentOS continues / does not optout
|
|
||||||
(should trigger on CentOS7 only)
|
|
||||||
'''
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
unexpected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS.'
|
|
||||||
' Deprecated PHP may be in use.')
|
|
||||||
assert unexpected_stdout not in package_manager_detect.stdout
|
|
||||||
# ensure remi was not installed on latest CentOS
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_user_optout_skipped_centos_gte_8(host):
|
|
||||||
'''
|
|
||||||
confirms installer skips user opt-out of installing PHP7 from REMI on
|
|
||||||
latest CentOS (should trigger on CentOS7 only)
|
|
||||||
(php not currently installed)
|
|
||||||
'''
|
|
||||||
# Whiptail dialog returns Cancel for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '1')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
unexpected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS.'
|
|
||||||
' Deprecated PHP may be in use.')
|
|
||||||
assert unexpected_stdout not in package_manager_detect.stdout
|
|
||||||
# ensure remi was not installed on latest CentOS
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_upgrade_user_optin_skipped_centos_gte_8(host):
|
|
||||||
'''
|
|
||||||
confirms installer skips user opt-in to installing PHP7 from REMI on
|
|
||||||
latest CentOS (should trigger on CentOS7 only)
|
|
||||||
(php not currently installed)
|
|
||||||
'''
|
|
||||||
# Whiptail dialog returns Continue for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '0')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
assert 'opt-out' not in package_manager_detect.stdout
|
|
||||||
unexpected_stdout = info_box + (' Enabling Remi\'s RPM repository '
|
|
||||||
'(https://rpms.remirepo.net)')
|
|
||||||
assert unexpected_stdout not in package_manager_detect.stdout
|
|
||||||
unexpected_stdout = tick_box + (' Remi\'s RPM repository has '
|
|
||||||
'been enabled for PHP7')
|
|
||||||
assert unexpected_stdout not in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
@@ -7,119 +7,21 @@ from .conftest import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_release_supported_version_check_centos(host):
|
|
||||||
'''
|
|
||||||
confirms installer exits on unsupported releases of CentOS
|
|
||||||
'''
|
|
||||||
# modify /etc/redhat-release to mock an unsupported CentOS release
|
|
||||||
host.run('echo "CentOS Linux release 6.9" > /etc/redhat-release')
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
expected_stdout = cross_box + (' CentOS 6 is not supported.')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
expected_stdout = 'Please update to CentOS release 7 or later'
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
|
|
||||||
|
|
||||||
def test_enable_epel_repository_centos(host):
|
def test_enable_epel_repository_centos(host):
|
||||||
'''
|
"""
|
||||||
confirms the EPEL package repository is enabled when installed on CentOS
|
confirms the EPEL package repository is enabled when installed on CentOS
|
||||||
'''
|
"""
|
||||||
package_manager_detect = host.run('''
|
package_manager_detect = host.run(
|
||||||
|
"""
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
package_manager_detect
|
package_manager_detect
|
||||||
select_rpm_php
|
"""
|
||||||
''')
|
)
|
||||||
expected_stdout = info_box + (' Enabling EPEL package repository '
|
expected_stdout = info_box + (
|
||||||
'(https://fedoraproject.org/wiki/EPEL)')
|
" Enabling EPEL package repository " "(https://fedoraproject.org/wiki/EPEL)"
|
||||||
|
)
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
assert expected_stdout in package_manager_detect.stdout
|
||||||
expected_stdout = tick_box + ' Installed epel-release'
|
expected_stdout = tick_box + " Installed"
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
assert expected_stdout in package_manager_detect.stdout
|
||||||
epel_package = host.package('epel-release')
|
epel_package = host.package("epel-release")
|
||||||
assert epel_package.is_installed
|
assert epel_package.is_installed
|
||||||
|
|
||||||
|
|
||||||
def test_php_version_lt_7_detected_upgrade_default_optout_centos(host):
|
|
||||||
'''
|
|
||||||
confirms the default behavior to opt-out of upgrading to PHP7 from REMI
|
|
||||||
'''
|
|
||||||
# first we will install the default php version to test installer behavior
|
|
||||||
php_install = host.run('yum install -y php')
|
|
||||||
assert php_install.rc == 0
|
|
||||||
php_package = host.package('php')
|
|
||||||
default_centos_php_version = php_package.version.split('.')[0]
|
|
||||||
if int(default_centos_php_version) >= 7: # PHP7 is supported/recommended
|
|
||||||
pytest.skip("Test deprecated . Detected default PHP version >= 7")
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
expected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS. '
|
|
||||||
'Deprecated PHP may be in use.')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_version_lt_7_detected_upgrade_user_optout_centos(host):
|
|
||||||
'''
|
|
||||||
confirms installer behavior when user opt-out to upgrade to PHP7 via REMI
|
|
||||||
'''
|
|
||||||
# first we will install the default php version to test installer behavior
|
|
||||||
php_install = host.run('yum install -y php')
|
|
||||||
assert php_install.rc == 0
|
|
||||||
php_package = host.package('php')
|
|
||||||
default_centos_php_version = php_package.version.split('.')[0]
|
|
||||||
if int(default_centos_php_version) >= 7: # PHP7 is supported/recommended
|
|
||||||
pytest.skip("Test deprecated . Detected default PHP version >= 7")
|
|
||||||
# Whiptail dialog returns Cancel for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '1')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
''')
|
|
||||||
expected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS. '
|
|
||||||
'Deprecated PHP may be in use.')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|
||||||
|
|
||||||
def test_php_version_lt_7_detected_upgrade_user_optin_centos(host):
|
|
||||||
'''
|
|
||||||
confirms installer behavior when user opt-in to upgrade to PHP7 via REMI
|
|
||||||
'''
|
|
||||||
# first we will install the default php version to test installer behavior
|
|
||||||
php_install = host.run('yum install -y php')
|
|
||||||
assert php_install.rc == 0
|
|
||||||
php_package = host.package('php')
|
|
||||||
default_centos_php_version = php_package.version.split('.')[0]
|
|
||||||
if int(default_centos_php_version) >= 7: # PHP7 is supported/recommended
|
|
||||||
pytest.skip("Test deprecated . Detected default PHP version >= 7")
|
|
||||||
# Whiptail dialog returns Continue for user prompt
|
|
||||||
mock_command('whiptail', {'*': ('', '0')}, host)
|
|
||||||
package_manager_detect = host.run('''
|
|
||||||
source /opt/pihole/basic-install.sh
|
|
||||||
package_manager_detect
|
|
||||||
select_rpm_php
|
|
||||||
install_dependent_packages PIHOLE_WEB_DEPS[@]
|
|
||||||
''')
|
|
||||||
expected_stdout = info_box + (' User opt-out of PHP 7 upgrade on CentOS. '
|
|
||||||
'Deprecated PHP may be in use.')
|
|
||||||
assert expected_stdout not in package_manager_detect.stdout
|
|
||||||
expected_stdout = info_box + (' Enabling Remi\'s RPM repository '
|
|
||||||
'(https://rpms.remirepo.net)')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
expected_stdout = tick_box + (' Remi\'s RPM repository has '
|
|
||||||
'been enabled for PHP7')
|
|
||||||
assert expected_stdout in package_manager_detect.stdout
|
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert remi_package.is_installed
|
|
||||||
updated_php_package = host.package('php')
|
|
||||||
updated_php_version = updated_php_package.version.split('.')[0]
|
|
||||||
assert int(updated_php_version) == 7
|
|
||||||
|
|||||||
@@ -6,60 +6,70 @@ from .conftest import (
|
|||||||
|
|
||||||
|
|
||||||
def mock_selinux_config(state, host):
|
def mock_selinux_config(state, host):
|
||||||
'''
|
"""
|
||||||
Creates a mock SELinux config file with expected content
|
Creates a mock SELinux config file with expected content
|
||||||
'''
|
"""
|
||||||
# validate state string
|
# validate state string
|
||||||
valid_states = ['enforcing', 'permissive', 'disabled']
|
valid_states = ["enforcing", "permissive", "disabled"]
|
||||||
assert state in valid_states
|
assert state in valid_states
|
||||||
# getenforce returns the running state of SELinux
|
# getenforce returns the running state of SELinux
|
||||||
mock_command('getenforce', {'*': (state.capitalize(), '0')}, host)
|
mock_command("getenforce", {"*": (state.capitalize(), "0")}, host)
|
||||||
# create mock configuration with desired content
|
# create mock configuration with desired content
|
||||||
host.run('''
|
host.run(
|
||||||
|
"""
|
||||||
mkdir /etc/selinux
|
mkdir /etc/selinux
|
||||||
echo "SELINUX={state}" > /etc/selinux/config
|
echo "SELINUX={state}" > /etc/selinux/config
|
||||||
'''.format(state=state.lower()))
|
""".format(
|
||||||
|
state=state.lower()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_selinux_enforcing_exit(host):
|
def test_selinux_enforcing_exit(host):
|
||||||
'''
|
"""
|
||||||
confirms installer prompts to exit when SELinux is Enforcing by default
|
confirms installer prompts to exit when SELinux is Enforcing by default
|
||||||
'''
|
"""
|
||||||
mock_selinux_config("enforcing", host)
|
mock_selinux_config("enforcing", host)
|
||||||
check_selinux = host.run('''
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
checkSelinux
|
checkSelinux
|
||||||
''')
|
"""
|
||||||
expected_stdout = cross_box + ' Current SELinux: Enforcing'
|
)
|
||||||
|
expected_stdout = cross_box + " Current SELinux: enforcing"
|
||||||
assert expected_stdout in check_selinux.stdout
|
assert expected_stdout in check_selinux.stdout
|
||||||
expected_stdout = 'SELinux Enforcing detected, exiting installer'
|
expected_stdout = "SELinux Enforcing detected, exiting installer"
|
||||||
assert expected_stdout in check_selinux.stdout
|
assert expected_stdout in check_selinux.stdout
|
||||||
assert check_selinux.rc == 1
|
assert check_selinux.rc == 1
|
||||||
|
|
||||||
|
|
||||||
def test_selinux_permissive(host):
|
def test_selinux_permissive(host):
|
||||||
'''
|
"""
|
||||||
confirms installer continues when SELinux is Permissive
|
confirms installer continues when SELinux is Permissive
|
||||||
'''
|
"""
|
||||||
mock_selinux_config("permissive", host)
|
mock_selinux_config("permissive", host)
|
||||||
check_selinux = host.run('''
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
checkSelinux
|
checkSelinux
|
||||||
''')
|
"""
|
||||||
expected_stdout = tick_box + ' Current SELinux: Permissive'
|
)
|
||||||
|
expected_stdout = tick_box + " Current SELinux: permissive"
|
||||||
assert expected_stdout in check_selinux.stdout
|
assert expected_stdout in check_selinux.stdout
|
||||||
assert check_selinux.rc == 0
|
assert check_selinux.rc == 0
|
||||||
|
|
||||||
|
|
||||||
def test_selinux_disabled(host):
|
def test_selinux_disabled(host):
|
||||||
'''
|
"""
|
||||||
confirms installer continues when SELinux is Disabled
|
confirms installer continues when SELinux is Disabled
|
||||||
'''
|
"""
|
||||||
mock_selinux_config("disabled", host)
|
mock_selinux_config("disabled", host)
|
||||||
check_selinux = host.run('''
|
check_selinux = host.run(
|
||||||
|
"""
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
checkSelinux
|
checkSelinux
|
||||||
''')
|
"""
|
||||||
expected_stdout = tick_box + ' Current SELinux: Disabled'
|
)
|
||||||
|
expected_stdout = tick_box + " Current SELinux: disabled"
|
||||||
assert expected_stdout in check_selinux.stdout
|
assert expected_stdout in check_selinux.stdout
|
||||||
assert check_selinux.rc == 0
|
assert check_selinux.rc == 0
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
def test_epel_and_remi_not_installed_fedora(host):
|
def test_epel_and_remi_not_installed_fedora(host):
|
||||||
'''
|
"""
|
||||||
confirms installer does not attempt to install EPEL/REMI repositories
|
confirms installer does not attempt to install EPEL/REMI repositories
|
||||||
on Fedora
|
on Fedora
|
||||||
'''
|
"""
|
||||||
package_manager_detect = host.run('''
|
package_manager_detect = host.run(
|
||||||
|
"""
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
package_manager_detect
|
package_manager_detect
|
||||||
select_rpm_php
|
"""
|
||||||
''')
|
)
|
||||||
assert package_manager_detect.stdout == ''
|
assert package_manager_detect.stdout == ""
|
||||||
|
|
||||||
epel_package = host.package('epel-release')
|
epel_package = host.package("epel-release")
|
||||||
assert not epel_package.is_installed
|
assert not epel_package.is_installed
|
||||||
remi_package = host.package('remi-release')
|
|
||||||
assert not remi_package.is_installed
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _centos_7.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py ./test_centos_7_support.py
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py38
|
envlist = py3
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
whitelist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _centos_8.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker build -f _centos_8.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py ./test_centos_8_support.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_centos_common_support.py
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py38
|
envlist = py3
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
whitelist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _debian_10.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker build -f _debian_10.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py38
|
envlist = py3
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
whitelist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _debian_11.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker build -f _debian_11.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _debian_9.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _fedora_33.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _fedora_34.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
|
||||||
8
test/tox.fedora_35.ini
Normal file
8
test/tox.fedora_35.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
commands = docker build -f _fedora_35.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
||||||
8
test/tox.fedora_36.ini
Normal file
8
test/tox.fedora_36.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
commands = docker build -f _fedora_36.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py ./test_fedora_support.py
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _ubuntu_16.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _ubuntu_18.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py38
|
envlist = py3
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
whitelist_externals = docker
|
allowlist_externals = docker
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = docker build -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../
|
commands = docker build -f _ubuntu_20.Dockerfile -t pytest_pihole:test_container ../
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
[tox]
|
|
||||||
envlist = py38
|
|
||||||
|
|
||||||
[testenv]
|
|
||||||
whitelist_externals = docker
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = docker build -f _ubuntu_21.Dockerfile -t pytest_pihole:test_container ../
|
|
||||||
pytest {posargs:-vv -n auto} ./test_automated_install.py
|
|
||||||
8
test/tox.ubuntu_22.ini
Normal file
8
test/tox.ubuntu_22.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[tox]
|
||||||
|
envlist = py3
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
allowlist_externals = docker
|
||||||
|
deps = -rrequirements.txt
|
||||||
|
commands = docker build -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../
|
||||||
|
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py
|
||||||
Reference in New Issue
Block a user