mirror of
https://github.com/unifi-utilities/unifios-utilities.git
synced 2024-08-30 18:32:21 +00:00
Compare commits
No commits in common. "nextdns-1.7.1" and "main" have entirely different histories.
nextdns-1.
...
main
9
.gitattributes
vendored
9
.gitattributes
vendored
@ -1,9 +0,0 @@
|
||||
*.md filter=lfs diff=lfs merge=lfs -text
|
||||
*.sh filter=lfs diff=lfs merge=lfs -text
|
||||
*.service filter=lfs diff=lfs merge=lfs -text
|
||||
*.conflist filter=lfs diff=lfs merge=lfs -text
|
||||
*.yml filter=lfs diff=lfs merge=lfs -text
|
||||
*.conf filter=lfs diff=lfs merge=lfs -text
|
||||
*.gitignore filter=lfs diff=lfs merge=lfs -text
|
||||
*.deb filter=lfs diff=lfs merge=lfs -text
|
||||
* text !filter !merge !diff
|
7
.github/CODEOWNERS
vendored
Normal file
7
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
podman-update/build @mazzy89 @boostchicken
|
||||
run-pihole @boostchicken
|
||||
on_boot_scripts @boostchicken
|
||||
wireguard-go @boostchicken
|
||||
dns-common @boostchicken
|
||||
container-commmon @boostchicken
|
||||
on-boot-script/remote_install.sh @gtrabanco
|
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@ -1,4 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: boostchicken
|
||||
custom: ["paypal.me/boostchicken"]
|
44
.github/workflows/nextdns.yml
vendored
Normal file
44
.github/workflows/nextdns.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: NextDNS container
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
paths:
|
||||
- nextdns/docker/Dockerfile
|
||||
schedule:
|
||||
- cron: "0 0 */15 * *"
|
||||
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set the version
|
||||
id: set_version
|
||||
run: |
|
||||
echo VERSION=$(curl --silent "https://api.github.com/repos/nextdns/nextdns/releases/latest" | jq -r '.["tag_name"]')>> $GITHUB_ENV
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
-
|
||||
name: build pihole $VERSION
|
||||
run: docker buildx build --platform=linux/amd64,linux/arm64 --build-arg VERSION=${{ env.VERSION }} nextdns/docker -t boostchicken/nextdns:latest -t boostchicken/nextdns:${{ env.VERSION }} --push
|
41
.github/workflows/pihole-dote.yml
vendored
Normal file
41
.github/workflows/pihole-dote.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: Pihole DoTE Container
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
paths:
|
||||
- run-pihole/DoTE.Dockerfile
|
||||
schedule:
|
||||
- cron: "0 0 */15 * *"
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set the version
|
||||
id: set_version
|
||||
run: |
|
||||
echo VERSION=$(curl --silent "https://api.github.com/repos/pi-hole/docker-pi-hole/releases/latest" | jq -r '.["tag_name"]')>> $GITHUB_ENV
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: build pihole dote
|
||||
run: docker buildx build --platform=linux/amd64,linux/arm64 --build-arg VERSION=${{ env.VERSION }} run-pihole -f run-pihole/DoTE.Dockerfile -t boostchicken/pihole-dote:latest -t boostchicken/pihole-dote:${{ env.VERSION }} --push
|
46
.github/workflows/pihole.yml
vendored
Normal file
46
.github/workflows/pihole.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: Pihole DoH Container
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
paths:
|
||||
- run-pihole/Dockerfile
|
||||
schedule:
|
||||
- cron: "0 0 */15 * *"
|
||||
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set the version
|
||||
id: set_version
|
||||
run: |
|
||||
echo VERSION=$(curl --silent "https://api.github.com/repos/pi-hole/docker-pi-hole/releases/latest" | jq -r '.["tag_name"]')>> $GITHUB_ENV
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
version: v0.10.1
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
-
|
||||
name: build pihole $VERSION
|
||||
run: docker buildx build --provenance=false --platform=linux/amd64,linux/arm64 --build-arg VERSION=${{ env.VERSION }} run-pihole -t boostchicken/pihole:latest -t boostchicken/pihole:${{ env.VERSION }} --push
|
56
.github/workflows/podman-udm.yml
vendored
Normal file
56
.github/workflows/podman-udm.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
name: UDM Podman
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
paths:
|
||||
- 'podman-update/build/Dockerfile'
|
||||
- 'podman-update/build/podman.Makefile.UDM-Base.patch'
|
||||
- 'podman-update/build/*.conf'
|
||||
- 'podman-update/build/*.json'
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'podman-update/build/Dockerfile'
|
||||
- 'podman-update/build/podman.Makefile.UDM-Base.patch'
|
||||
- 'podman-update/build/*.conf'
|
||||
- 'podman-update/build/*.json'
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Docker Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2.1.0
|
||||
with:
|
||||
platforms: arm64
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2.5.0
|
||||
- name: Build the Docker image
|
||||
run: DOCKER_BUILDKIT=1 docker build --file podman-update/build/Dockerfile --build-arg UDM_PLATFORM=UDM-Base --tag boostchicken:udm-podman podman-update/build/
|
||||
- name: Docker Extract
|
||||
id: extract
|
||||
uses: boostchicken-dev/actions-docker-extract@v3
|
||||
with:
|
||||
# Docker Image to extract files from
|
||||
image: boostchicken:udm-podman
|
||||
# Path (from root) to a file or directory within Image
|
||||
path: /tmp/install/.
|
||||
|
||||
- name: Generate new tag version
|
||||
id: version
|
||||
uses: flynshue/version-action@v0.0.1
|
||||
|
||||
- name: Upload Podman Install
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
with:
|
||||
path: ${{ steps.extract.outputs.destination }}
|
||||
name: podman-udm-${{ steps.version.outputs.version }}
|
||||
retention-days: 90
|
57
.github/workflows/podman-udmp-udmse.yml
vendored
Normal file
57
.github/workflows/podman-udmp-udmse.yml
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
name: UDM-SE/PRO Podman
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
paths:
|
||||
- 'podman-update/build/Dockerfile'
|
||||
- 'podman-update/build/podman.Makefile.UDM-Pro-SE.patch'
|
||||
- 'podman-update/build/*.conf'
|
||||
- 'podman-update/build/*.json'
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'podman-update/build/Dockerfile'
|
||||
- 'podman-update/build/podman.Makefile.UDM-Pro-SE.patch'
|
||||
- 'podman-update/build/*.conf'
|
||||
- 'podman-update/build/*.json'
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- name: Docker Setup QEMU
|
||||
uses: docker/setup-qemu-action@v3.0.0
|
||||
with:
|
||||
platforms: arm64
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.0.0
|
||||
- name: Build the Docker image
|
||||
run: DOCKER_BUILDKIT=1 docker build --file podman-update/build/Dockerfile --build-arg UDM_PLATFORM=UDM-Pro-SE --tag boostchicken:udm-podman podman-update/build/
|
||||
- name: Docker Extract
|
||||
id: extract
|
||||
uses: boostchicken-dev/actions-docker-extract@v3
|
||||
with:
|
||||
# Docker Image to extract files from
|
||||
image: boostchicken:udm-podman
|
||||
# Path (from root) to a file or directory within Image
|
||||
path: /tmp/install/.
|
||||
|
||||
- name: Generate new tag version
|
||||
id: version
|
||||
uses: flynshue/version-action@v0.0.1
|
||||
|
||||
- name: Upload Podman Install
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ steps.extract.outputs.destination }}
|
||||
name: podman-udmse-udmpro-${{ steps.version.outputs.version }}
|
||||
retention-days: 90
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1 +1,6 @@
|
||||
/.idea/
|
||||
/**/debian/files
|
||||
/**/debian/*.substvars
|
||||
debhelper-build-stamp
|
||||
.debhelper
|
||||
Wiki_Wireguard.md
|
||||
|
@ -2,41 +2,66 @@
|
||||
|
||||
## Features
|
||||
|
||||
1. Run AdguardHome on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti
|
||||
1. Run AdguardHome on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti
|
||||
2. Persists through reboots and firmware updates.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have setup the on boot script described [here](https://github.com/boostchicken/udm-utilities/tree/master/on-boot-script)
|
||||
1. AdguardHome persists through firmware updates as it will store the configuration in a folder (you need to create this). It needs 2 folders, a Work and Configuration folder. Please create the 2 folders in "/mnt/data/". In my example I created "AdguardHome-Confdir" and "AdguardHome-Workdir"
|
||||
1. You have setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
1. AdguardHome persists through firmware updates as it will store the configuration in a folder (you need to create this). It needs 2 folders, a Work and Configuration folder. Please create the 2 folders in "/data/". In my example I created "AdguardHome-Confdir" and "AdguardHome-Workdir"
|
||||
|
||||
## Customization
|
||||
|
||||
* Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP address of the container.
|
||||
* Update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with your own values
|
||||
* If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments.
|
||||
- Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP and MAC address of the container.
|
||||
- Update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with your own values
|
||||
- If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments.
|
||||
|
||||
## Steps
|
||||
|
||||
1. On your controller, make a Corporate network with no DHCP server and give it a VLAN. For this example we are using VLAN 5.
|
||||
1. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to /mnt/data/on_boot.d and update its values to reflect your environment
|
||||
1. Execute /mnt/data/on_boot.d/10-dns.sh
|
||||
1. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to /mnt/data/podman/cni. This will create your podman macvlan network
|
||||
1. Run the AdguardHome docker container, be sure to make the directories for your persistent AdguardHome configuration. They are mounted as volumes in the command below.
|
||||
Please note if you have firmware v2 or above you have to copy all files into /data instead of /mnt/data. You can see what version you are running by running: ubnt-device-info firmware
|
||||
|
||||
```shell script
|
||||
mkdir /mnt/data/AdguardHome-Confdir
|
||||
mkdir /mnt/data/AdguardHome-Workdir
|
||||
|
||||
podman run -d --network dns --restart always \
|
||||
--name adguardhome \
|
||||
-v "/mnt/data/AdguardHome-Confdir/:/opt/adguardhome/conf/" \
|
||||
-v "/mnt/data/AdguardHome-Workdir/:/opt/adguardhome/work/" \
|
||||
--dns=127.0.0.1 --dns=1.1.1.1 \
|
||||
--hostname adguardhome \
|
||||
adguard/adguardhome:latest
|
||||
```
|
||||
1. Check if you have either `/mnt/data/` or `/data/` and use the correct one below.
|
||||
2. Copy [05-install-cni-plugins.sh](../cni-plugins/05-install-cni-plugins.sh) to /data/on_boot.d
|
||||
3. On your controller, make a Corporate network with no DHCP server and give it a VLAN. For this example we are using VLAN 5. You should confirm the bridge is created for this VLAN by running `netstat -r` otherwise the script will fail. If it is not there, initiate a provisioning of the UDM (Controller > UDM > Config > Manage Device > Force provision).
|
||||
4. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to `/data/on_boot.d` and update its values to reflect your environment
|
||||
5. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to `/data/podman/cni` after generating a MAC address. This will create your podman macvlan network.
|
||||
6. Execute /data/on_boot.d/05-install-cni-plugins.sh
|
||||
7. Execute `/data/on_boot.d/10-dns.sh`
|
||||
8. Run the AdguardHome docker container, be sure to make the directories for your persistent AdguardHome configuration. They are mounted as volumes in the command below.
|
||||
|
||||
1. Browse to 10.0.5.3:3000 and follow the setup wizard
|
||||
1. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs.
|
||||
1. Access the AdguardHome like you would normally.
|
||||
```shell script
|
||||
mkdir /data/AdguardHome-Confdir
|
||||
mkdir /data/AdguardHome-Workdir
|
||||
|
||||
podman run -d --network dns --restart always \
|
||||
--name adguardhome \
|
||||
-v "/data/AdguardHome-Confdir/:/opt/adguardhome/conf/" \
|
||||
-v "/data/AdguardHome-Workdir/:/opt/adguardhome/work/" \
|
||||
--dns=127.0.0.1 --dns=1.1.1.1 \
|
||||
--hostname adguardhome \
|
||||
adguard/adguardhome:latest
|
||||
```
|
||||
|
||||
9. Browse to 10.0.5.3:3000 and follow the setup wizard
|
||||
10. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs.
|
||||
11. Access the AdguardHome like you would normally.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you get the following error:
|
||||
|
||||
```
|
||||
Error adding network: failed to create macvlan: cannot assign requested address
|
||||
```
|
||||
|
||||
When starting the container then the MAC address you generated is not good. You can cheat at this point and look at the address of `br$VLAN.mac` with `ifconfig br$VLAN.mac` and use that value.
|
||||
|
||||
To start over you must remove the container and the macvlan device:
|
||||
|
||||
```
|
||||
podman container rm adguardhome
|
||||
podman network rm dns -f # expect an error here
|
||||
ip link delete br$VLAN.mac
|
||||
```
|
||||
|
||||
You can now run `10-dns.sh` again and start the container again.
|
||||
|
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
Slack (https://join.slack.com/t/boostchicken/shared_invite/zt-fcjszaw4-2ZuNFxIQnrpjxixnm17LXQ).
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
3
CONTRIBUTING.md
Normal file
3
CONTRIBUTING.md
Normal file
@ -0,0 +1,3 @@
|
||||
All pull requests on any content are welcome!
|
||||
Anything you find useful.
|
||||
I will review all PRs, just please include what your changes does and why you did it.
|
154
README.md
154
README.md
@ -1,62 +1,168 @@
|
||||
# udm-utilities [](https://join.slack.com/t/boostchicken/shared_invite/zt-fcjszaw4-2ZuNFxIQnrpjxixnm17LXQ)
|
||||
# unifios-utilities [](https://discord.gg/8zqrQJFghg) [](https:///www.cloudflare.com)
|
||||
|
||||
A collection of things to enhance the capabilities of your Unifi Dream Machine or Dream Machine Pro.
|
||||
[](https://github.com/unifi-utilities/unifios-utilities/actions/workflows/podman-udm.yml)
|
||||
[](https://github.com/unifi-utilities/unifios-utilities/actions/workflows/podman-udmp-udmse.yml)
|
||||
|
||||
## Contributing
|
||||
## Branches
|
||||
1. [1.12.x](https://github.com/unifi-utilities/unifios-utilities/tree/v1.12.x) - Support for 1.x.x firmware line
|
||||
1. [main](https://github.com/unifi-utilities/unifios-utilities) - Support for 2.4.x and above
|
||||
|
||||
Pull Requests welcome! If you use this functionality to do new cool stuff to your UDM/P please send a PR and share it with the community!
|
||||
### Current Branch is main, supporting UniFi OS 2.5.x
|
||||
|
||||
A collection of things to enhance the capabilities of your Unifi Dream Machine, Dream Machine Pro or UXG-Pro.
|
||||
|
||||
### ⚠️ Breaking Changes for UniFi OS 3.x
|
||||
|
||||
UniFi OS 3.x no longer supports podman. The utilities in this respository **may not work as documented**. For alternatives, review the documentation in [nspawn-container](https://github.com/unifi-utilities/unifios-utilities/tree/main/nspawn-container) or consider direct installations like [wpa_supplicant-UniFi-OS-3.x for AT&T Fiber](https://github.com/jphamdev/wpa_supplicant-UniFi-OS-3.x).
|
||||
|
||||
-----
|
||||
## Custom Kernel
|
||||
|
||||
If you want to do a custom kernel with wireguard support, multicast, multipath routing that is now a possiblity.
|
||||
Please see the repo and please use at your own risk. This a much larger change than anything in this repo.
|
||||
|
||||
[udm-kernel-tools](https://github.com/fabianishere/udm-kernel-tools)
|
||||
|
||||
## Custom Podman Builds for UDM-SE
|
||||
|
||||
All artifacts can be found on IPFS
|
||||
|
||||
[IPFS Gateway](https://unifi.boostchicken.io) 
|
||||
|
||||
Extract the zip to the root of your device!
|
||||
Look at the assets on the Podman workflow.
|
||||
|
||||
### UDM Base
|
||||
Standard Image for base UDM, systemd removed
|
||||
|
||||
### UDM Pro / SE
|
||||
Base build with apparmor, systemd, devicemapper removal, and overlay kept
|
||||
|
||||
Works on PRO on 2.x, for 1.x use the UDM Base still.
|
||||
|
||||
*Does not work on 3.x use nspawn-container*
|
||||
|
||||
## macvlan kernel module for UDR
|
||||
|
||||
Ui have stopped building the `macvlan` kernel module into the kernel for the UDR, which means containers cannot
|
||||
have their own routable IPs out of the box. This module is being built and distributed separately, and can be found
|
||||
at [macvlan-unifi-udr](https://github.com/whi-tw/macvlan-unifi-udr).
|
||||
|
||||
## General Tools
|
||||
|
||||
### on-boot-script
|
||||
### on-boot-script-2.x
|
||||
|
||||
Do this first. Enables `init.d` style scripts to run on every boot of your UDM.
|
||||
Includes examples to run `wpa-supplicant/eap-proxy` and/or `ntop-ng` on startup.
|
||||
Follow this [readme](https://github.com/unifi-utilities/unifios-utilities/blob/main/on-boot-script/README.md).
|
||||
|
||||
Enables init.d style scripts to run on every boot of your UDM. Includes a wpa-supplicant/eap-proxy example.
|
||||
**It enables complete customization of your UDM/P and fills the gap that config.gateway.json left behind.**
|
||||
|
||||
### nspawn-container
|
||||
Enables containers on UniFiOS 3.x, this replaces podman.
|
||||
|
||||
### podman-update
|
||||
|
||||
Updates Podman, conmon, and runc to a recent version.This allows docker-compose usage as well.
|
||||
|
||||
Works on PRO on 2.x, for 1.x use the UDM Base still.
|
||||
|
||||
**Does not working on 3.x use nspawn-container**
|
||||
|
||||
### container-common
|
||||
|
||||
Apply this after on-boot-script.
|
||||
Updates container defaults to maintain **stable disk usage footprint** of custom containers.
|
||||
**Prevents logs filling up UDM storage full**.
|
||||
|
||||
### python
|
||||
|
||||
If you need python3 on your UDM, generally not recommended, can always use it in unifi-os container
|
||||
If you need python3 on your UDM, generally not recommended, can always use it in unifi-os container.
|
||||
|
||||
|
||||
## VPN Servers / Clients
|
||||
| Name | URL | Description |
|
||||
|------ |----- |------------- |
|
||||
|wireguard-go | | Run a Wireguard client/server |
|
||||
| WireGuard kernel module | <https://github.com/tusc/wireguard-kmod> | Uses a prebuilt linux kernel module, without the need to move to a custom kernel. |
|
||||
| OpenConnect VPN | <https://github.com/shuguet/openconnect-udm> | OpenConnect VPN Client for the UniFi Dream Machine Pro (Unofficial).|
|
||||
| split-vpn | <https://github.com/peacey/split-vpn> |A split tunnel VPN script for the UDM with policy based routing. This helper script can be used on your UDM to route select VLANs, clients, or even domains through a VPN connection. It supports OpenVPN, WireGuard, and OpenConnect (Cisco AnyConnect) clients running directly on your UDM, and external VPN clients running on other servers on your network. |
|
||||
| Zerotier | <https://zerotier.com> |ZeroTier provides network control and P2P functionality · Use ZeroTier to create products which run on their own decentralized networks |
|
||||
|
||||
### wireguard-go
|
||||
|
||||
Run a Wireguard client/server on your UDM/P. Utilizes wireguard-go, not linux kernel modules. The performance will take a hit due to that.
|
||||
|
||||
## DNS Providers
|
||||
|
||||
Install a DNS server that functions as a network-wide ad and tracker blocker, and which can also securely proxy encrypted DNS requests to an upstream DNS provider.
|
||||
Begin by following the instructions to setup [on-boot-script](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script) and [dns-common](https://github.com/unifi-utilities/unifios-utilities/tree/main/dns-common/on_boot.d).
|
||||
Then, follow the guides below to setup either Pi-Hole, NextDNS, or AdGuard Home.
|
||||
|
||||
### dns-common
|
||||
|
||||
Configurations for DNS containers, both IPv4 and IPv6. Utilizes MacVLAN CNI plugins to completely isolate the network stack.
|
||||
|
||||
### run-pihole
|
||||
|
||||
Run pihole on your UDM with podman.
|
||||
Base configuration for DNS server containers, both IPv4 and IPv6.
|
||||
Utilizes MacVLAN CNI plugins to completely isolate the network stack.
|
||||
|
||||
### nextdns
|
||||
|
||||
Run NextDNS on your UDM with podman.
|
||||
|
||||
### run-pihole
|
||||
|
||||
[](https://hub.docker.com/u/boostchicken)
|
||||
|
||||
PiHole w/ DoH Image.
|
||||
Run Pi-hole on your UDM with podman.
|
||||
Also contains custom image for Pi-hole with `cloudflared`.
|
||||
|
||||
### PiHole with DoTe
|
||||
[](https://hub.docker.com/r/pombeirp/pihole-dote)
|
||||
|
||||
Designed by: <https://github.com/chrisstaite/DoTe/>
|
||||
|
||||
Alternative to mine which uses DoTe
|
||||
|
||||
### AdguardHome
|
||||
|
||||
Run AdguardHome on your UDM with podman.
|
||||
|
||||
### Cloudflare DDNS
|
||||

|
||||
|
||||
Update your cloudflare domains from your UDM with podman.
|
||||
|
||||
## Cool projects you can use with this
|
||||
|
||||
### multicast-relay
|
||||
| Name | URL | Description |
|
||||
|------ |----- |------------- |
|
||||
|multicast-relay |<https://hub.docker.com/r/scyto/multicast-relay> | This is a docker container that implements <https://github.com/alsmith/multicast-relay> to provide mDNS and SSDP on a unifi dream machine. It will likely work on any multi homed host. |
|
||||
| [mosquitto](./mosquitto/) | <https://hub.docker.com/_/eclipse-mosquitto> | Eclipse Mosquitto is an open source **MQTT message broker** |
|
||||
| ntopng | <https://github.com/tusc/ntopng-udm> | Much better network stats for your UDM/P! Install this docker container and create an on_boot script to make sure it's always running. |
|
||||
| LetsEncrypt | <https://github.com/kchristensen/udm-le> |Provision and renew LetsEncrypt SSL certs from your UDM/P. |
|
||||
| ubios-cert | <https://github.com/alxwolf/ubios-cert> | Provision and renew SSL/TLS certificates from LetsEncrypt, ZeroSSL, BuyPass, Google and any other RFC8555-compliant CA. Runs `acme.sh` on your UDM, UDM Pro, UDM SE or UDR. No podman required, supports both V1.x and V2.x firmwares. Secure your HTTPS connections to device, WiFiman and Guest Portal. |
|
||||
| Unifi API Browser | <https://hub.docker.com/r/scyto/unifibrowser> | This is a docker container that implements <https://github.com/Art-of-WiFi/UniFi-API-browser> to provide a graphical tool to inspect the data structures available via the unifi API.Great if you are using the REST API for your own purposes and want to explore.Works with multiple controller versions. |
|
||||
|ubnt-auto-fan-speed |<https://github.com/renedis/ubnt-auto-fan-speed> | A shell script with the goal to make the UDM-Pro silenced while still having good thermal values. |
|
||||
|rclone | <https://rclone.org/> |Run rclone container with Web GUI for offsite backups. |
|
||||
|udm-proxy | <https://github.com/xpherism/udm-proxy> |Run a reverse proxy (using caddy in vlan) on the udm-pro. |
|
||||
| Telegram-Notifications On WAN Failover | <https://github.com/fire1ce/UDM-Failover-Telegram-Notifications> | Use telegram bot to be notified of a wan failover with local account|
|
||||
|
||||
<https://hub.docker.com/r/scyto/multicast-relay>
|
||||
[](https://cloudflare.com)
|
||||
|
||||
This is a docker container that implements <https://github.com/alsmith/multicast-relay> to provide mDNS and SSDP on a unifi dream machine. It will likely work on any multi homed host.
|
||||
|
||||
### ntopng
|
||||
## Unsupported / No longer maintained
|
||||
|
||||
<https://github.com/tusc/ntopng-udm>
|
||||
|
||||
Much better network stats for your UDM/P! Install this docker container and create an on_boot script to make sure it's always running.
|
||||
| Name | URL | Description |
|
||||
|------ |----- |------------- |
|
||||
|suricata | | Updates suricata to a recent version. Now in firmware |
|
||||
| Jumbo Frames | <https://github.com/kalenarndt/udmp-jumbo-frames> | native jumbo frame support for the UDM and UDM-Pro is added in the 1.12.13 EA firmware, support for the UDM-SE is not yet announced. |
|
||||
| UDM Persistent SSH Keys Script | <https://github.com/fire1ce/UDM-Persistent-SSH-Keys> | Stores SSH Keys. This functionality is now in firmware
|
||||
|
||||
### LetsEncrypt SSL Certs
|
||||
## Reimaging your UDM
|
||||
|
||||
<https://github.com/kchristensen/udm-le>
|
||||
Working in the shell means that mistakes can happen. Deleted directories or packages may break the underlying software that makes your UDM-Pro SE function as designed. Thankfully, Unifi Support seems to have provided the following process to help bring your UDM back to the stock image.
|
||||
|
||||
Provision and renew LetsEncrypt SSL certs from your UDM/P
|
||||
1. Remove the unit from your network and disconnect the cables from the unit.
|
||||
2. Press down the reset button for 40+ seconds without power and cables.
|
||||
3. Release the reset button and power the unit.
|
||||
4. Again press the reset button for 15+ seconds.
|
||||
|
||||
Thanks to user [cfallwell](https://github.com/cfallwell) for describing this fix [here](https://github.com/unifi-utilities/unifios-utilities/issues/428#issuecomment-1386212026).
|
||||
|
101
att-ipv6/10-att-ipv6.sh
Executable file
101
att-ipv6/10-att-ipv6.sh
Executable file
@ -0,0 +1,101 @@
|
||||
#! /bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Check if the directory exists
|
||||
if [ ! -d "$DATA_DIR/att-ipv6" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "$DATA_DIR/att-ipv6"
|
||||
echo "Directory '$DATA_DIR/att-ipv6' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '$DATA_DIR/att-ipv6' already exists. Moving on."
|
||||
fi
|
||||
|
||||
wan_iface="eth8" # "eth9" for UDM Pro WAN2
|
||||
vlans="br0" # "br0 br100 br101..."
|
||||
domain="example.invalid" # DNS domain
|
||||
dns6="[2001:4860:4860::8888],[2001:4860:4860::8844]" # Google
|
||||
|
||||
CONTAINER=att-ipv6
|
||||
confdir=${DATA_DIR}/att-ipv6
|
||||
|
||||
# main
|
||||
mkdir -p "${confdir}/dhcpcd"
|
||||
|
||||
test -f "${confdir}/dhcpcd.conf" || {
|
||||
: >"${confdir}/dhcpcd.conf.tmp"
|
||||
cat >>"${confdir}/dhcpcd.conf.tmp" <<EOF
|
||||
allowinterfaces ${wan_iface}
|
||||
nodev
|
||||
noup
|
||||
ipv6only
|
||||
nooption domain_name_servers
|
||||
nooption domain_name
|
||||
duid
|
||||
persistent
|
||||
option rapid_commit
|
||||
option interface_mtu
|
||||
require dhcp_server_identifier
|
||||
slaac private
|
||||
noipv6rs
|
||||
|
||||
interface ${wan_iface}
|
||||
ipv6rs
|
||||
ia_na 0
|
||||
EOF
|
||||
|
||||
ix=0
|
||||
for vv in $vlans; do
|
||||
echo " ia_pd ${ix} ${vv}/0"
|
||||
ix=$((ix + 1))
|
||||
done >>"${confdir}/dhcpcd.conf.tmp"
|
||||
mv "${confdir}/dhcpcd.conf.tmp" "${confdir}/dhcpcd.conf"
|
||||
}
|
||||
|
||||
test -f "${confdir}/att-ipv6-dnsmasq.conf" || {
|
||||
: >"${confdir}/att-ipv6-dnsmasq.conf.tmp"
|
||||
cat >>"${confdir}/att-ipv6-dnsmasq.conf.tmp" <<EOF
|
||||
#
|
||||
# via att-ipv6
|
||||
#
|
||||
enable-ra
|
||||
no-dhcp-interface=lo
|
||||
no-ping
|
||||
EOF
|
||||
|
||||
for vv in $vlans; do
|
||||
cat <<EOF
|
||||
|
||||
interface=${vv}
|
||||
dhcp-range=set:att-ipv6-${vv},::2,::7d1,constructor:${vv},slaac,ra-names,64,86400
|
||||
dhcp-option=tag:att-ipv6-${vv},option6:dns-server,${dns6}
|
||||
domain=${domain}|${vv}
|
||||
ra-param=${vv},high,0
|
||||
EOF
|
||||
done >>"${confdir}/att-ipv6-dnsmasq.conf.tmp"
|
||||
mv "${confdir}/att-ipv6-dnsmasq.conf.tmp" "${confdir}/att-ipv6-dnsmasq.conf"
|
||||
}
|
||||
|
||||
if podman container exists "$CONTAINER"; then
|
||||
podman start "$CONTAINER"
|
||||
else
|
||||
podman run -d --restart=always --name "$CONTAINER" -v "${confdir}/dhcpcd.conf:/etc/dhcpcd.conf" -v "${confdir}/dhcpcd:/var/lib/dhcpcd" --net=host --privileged ghcr.io/michaelw/dhcpcd
|
||||
fi
|
||||
|
||||
# Fix DHCP, assumes DHCPv6 is turned off in UI
|
||||
cp "${confdir}/att-ipv6-dnsmasq.conf" /run/dnsmasq.conf.d/
|
||||
start-stop-daemon -K -q -x /usr/sbin/dnsmasq
|
130
att-ipv6/README.md
Normal file
130
att-ipv6/README.md
Normal file
@ -0,0 +1,130 @@
|
||||
# AT&T IPv6
|
||||
|
||||
On ATT IPv6, the RG (residential gateway) receives a /60 prefix itself, but only hands out one /64 to routers in IP Passthrough mode, regardless how big of a prefix was requested. The RG keeps the lower 8 /64s for its own purposes (`2600:1700:X:yyy0::/63`), and Unifi normally only receives `2600:1700:X:yyyf::/64`.
|
||||
|
||||
This script enables UDM to receive up to 8 PDs on ATT IPv6 (tested with RG BGW320-500), usually starting at `2600:1700:X:yyyf::/64` down to `2600:1700:X:yyy8::/64`.
|
||||
Note that these may not always be assigned contiguous or in order.
|
||||
|
||||
The price to pay is that almost none of the IPv6 support native to UDM remains enabled, hence options like DHCPv6 cannot be changed in the UI anymore.
|
||||
Firewall and routing rules remain functional, however.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
2. You must set up the ATT RG in ["IP Passthrough" mode](https://patrickdomingues.com/2022/09/03/udm-pro-vpn-on-att-fiber-bgw320/)
|
||||
3. You must turn off IPv6 on the ATT WAN connection, AND on each network/VLAN (IPv6 Interface Type: None)
|
||||
4. You must add Firewall rules equivalent to (this can be done in the UI, select `Internet v6 Local` chain)
|
||||
```
|
||||
-A UBIOS_WAN_LOCAL_USER -p udp -m udp --sport 547 --dport 546 -j RETURN # select IPv6 Protocol "UDP" and create port groups for source port 547 and dest port 546
|
||||
-A UBIOS_WAN_LOCAL_USER -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j RETURN # select IPv6 Protocol "ICMPv6" and IPv6ICMP Type Name "Router Advertisement"
|
||||
```
|
||||
5. You may want to add a "Traffic Management" route on your ATT WAN device to access 192.168.1.254/32, so that you can access the RG after it is in passthrough mode.
|
||||
|
||||
## Customization
|
||||
|
||||
Near the top of `10-att-ipv6.sh`:
|
||||
|
||||
```sh
|
||||
wan_iface="eth8" # use "eth9" for UDM Pro WAN2
|
||||
vlans="br0" # "br0 br100 br101..."
|
||||
domain="example.invalid" # DNS domain
|
||||
dns6="[2001:4860:4860::8888],[2001:4860:4860::8844]" # Google
|
||||
```
|
||||
|
||||
This generates configuration files in directory `/data/att-ipv6`, if they don't exist.
|
||||
The files can be edited, or regenerated by deleting them and re-running the script.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
cd /data/on_boot.d
|
||||
curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/att-ipv6/10-att-ipv6.sh
|
||||
chmod +x 10-att-ipv6.sh
|
||||
./10-att-ipv6.sh
|
||||
```
|
||||
|
||||
The dhcpcd container being used is built [here](https://github.com/michaelw/dhcpcd-container/pkgs/container/dhcpcd)
|
||||
|
||||
## Validation
|
||||
|
||||
Running the script starts dhcpcd within the `att-ipv6` container on `eth8` (WAN1) and only for the default network (`br0`). This can be customized, see above.
|
||||
|
||||
To check that everything is working as expected, and the ATT RG delegates multiple prefixes:
|
||||
|
||||
On UDM:
|
||||
|
||||
```sh
|
||||
$ ip -6 r # should see a default route on the WAN interface, and a 2600:1700:X:Y::/64 prefix on each configured VLAN bridge interface
|
||||
2600:1700:X:yyy0::/64 dev eth9 proto ra metric 203 mtu 1500 pref medium
|
||||
2600:1700:X:yyyb::/64 dev br104 proto dhcp metric 235 pref medium
|
||||
2600:1700:X:yyyc::/64 dev br103 proto dhcp metric 234 pref medium
|
||||
2600:1700:X:yyyd::/64 dev br102 proto dhcp metric 233 pref medium
|
||||
2600:1700:X:yyye::/64 dev br101 proto dhcp metric 232 pref medium
|
||||
2600:1700:X:yyyf::/64 dev br0 proto dhcp metric 212 pref medium
|
||||
[...]
|
||||
```
|
||||
|
||||
```sh
|
||||
$ podman logs att-ipv6 # should see dhcpcd successfully acquiring prefixes
|
||||
[...]
|
||||
eth9: writing lease `/var/lib/dhcpcd/eth9.lease6'
|
||||
eth9: delegated prefix 2600:1700:X:yyyf::/64
|
||||
eth9: delegated prefix 2600:1700:X:yyye::/64
|
||||
eth9: delegated prefix 2600:1700:X:yyyd::/64
|
||||
eth9: delegated prefix 2600:1700:X:yyyc::/64
|
||||
eth9: delegated prefix 2600:1700:X:yyyb::/64
|
||||
br0: adding address 2600:1700:X:yyyf::1/64
|
||||
br0: pltime 3600 seconds, vltime 3600 seconds
|
||||
br0: executing `/lib/dhcpcd/dhcpcd-run-hooks' DELEGATED6
|
||||
br101: adding address 2600:1700:X:yyye::1/64
|
||||
br101: pltime 3600 seconds, vltime 3600 seconds
|
||||
br101: executing `/lib/dhcpcd/dhcpcd-run-hooks' DELEGATED6
|
||||
br102: adding address 2600:1700:X:yyyd::1/64
|
||||
br102: pltime 3600 seconds, vltime 3600 seconds
|
||||
br102: executing `/lib/dhcpcd/dhcpcd-run-hooks' DELEGATED6
|
||||
br103: adding address 2600:1700:X:yyyc::1/64
|
||||
br103: pltime 3600 seconds, vltime 3600 seconds
|
||||
br103: executing `/lib/dhcpcd/dhcpcd-run-hooks' DELEGATED6
|
||||
br104: adding address 2600:1700:X:yyyb::1/64
|
||||
br104: pltime 3600 seconds, vltime 3600 seconds
|
||||
br104: executing `/lib/dhcpcd/dhcpcd-run-hooks' DELEGATED6
|
||||
br0: adding route to 2600:1700:X:yyyf::/64
|
||||
br101: adding route to 2600:1700:X:yyye::/64
|
||||
br102: adding route to 2600:1700:X:yyyd::/64
|
||||
br103: adding route to 2600:1700:X:yyyc::/64
|
||||
br104: adding route to 2600:1700:X:yyyb::/64
|
||||
lo: deleting reject route to 2600:1700:X:yyyf::/64
|
||||
lo: deleting reject route to 2600:1700:X:yyye::/64
|
||||
lo: deleting reject route to 2600:1700:X:yyyd::/64
|
||||
lo: deleting reject route to 2600:1700:X:yyyc::/64
|
||||
lo: deleting reject route to 2600:1700:X:yyyb::/64
|
||||
[...]
|
||||
```
|
||||
|
||||
```sh
|
||||
$ ps auxw|grep dnsmasq # should see dnsmasq running
|
||||
```
|
||||
|
||||
On BGW320-500, check https://192.168.1.254/cgi-bin/lanstatistics.ha for multiple PDs in `IPv6 Delegated Prefix Subnet (including length)`.
|
||||
|
||||
On clients:
|
||||
|
||||
```
|
||||
ip -6 addr show # should see SLAAC and/or DHCPv6 addresses received (if not, check dnsmasq configuration in `/run/dnsmasq.conf.d`)
|
||||
```
|
||||
|
||||
### Useful commands
|
||||
|
||||
```sh
|
||||
# View dhcpcd logs to verify the container is running without error (ipv6 logs from dhcpcd are normal).
|
||||
podman logs att-ipv6
|
||||
|
||||
# Restart dhcpcd (e.g., after configuration change)
|
||||
podman exec -it dhcpcd -x
|
||||
|
||||
# Stop the container
|
||||
podman stop att-ipv6
|
||||
|
||||
# Remove the container
|
||||
podman rm att-ipv6
|
||||
```
|
45
cloudflare-ddns/README.md
Normal file
45
cloudflare-ddns/README.md
Normal file
@ -0,0 +1,45 @@
|
||||
# Cloudflare Dynamic DNS
|
||||
|
||||
## Features
|
||||
|
||||
- Update Multiple Subdomains
|
||||
- Proxy your traffic through cloudflare
|
||||
- Set a ttl
|
||||
|
||||
Complete feature list and documentation can be found [here](https://github.com/timothymiller/cloudflare-ddns)
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
2. You must have a cloudflare profile with at least one domain.
|
||||
3. You must have a valid cloudflare api token with correct permissions (see [complete documentation](https://github.com/timothymiller/cloudflare-ddns) for details)
|
||||
|
||||
## Customization
|
||||
|
||||
Update [config.json](configs/config.json) with the following options:
|
||||
|
||||
- your cloudflare api token
|
||||
- your zone id
|
||||
- each subdomain you'd like to point at your udm-pro
|
||||
- Set the proxied flag if you'd like cloudflare to proxy the records
|
||||
- Set the ttl value you'd like for your records
|
||||
|
||||
## Steps
|
||||
|
||||
1. Make a directory for your configuration, check if you have `/mnt/data/` or `/data/` and adjust accordingly.
|
||||
|
||||
```sh
|
||||
mkdir -p /data/cloudflare-ddns
|
||||
```
|
||||
|
||||
2. Create a [cloudflare-ddns configuration](configs/config.json) in `/data/cloudflare-ddns` and update the configuration to meet your needs.
|
||||
3. Copy [30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh) to `/data/on_boot.d`.
|
||||
. Execute /data/on_boot.d/[30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh)
|
||||
5. Execute `podman logs cloudflare-ddns` to verify the continer is running without error (ipv6 warnings are normal).
|
||||
|
||||
### Useful commands
|
||||
|
||||
```sh
|
||||
# view cloudflare-ddns logs to verify the continer is running without error (ipv6 warnings are normal).
|
||||
podman logs cloudflare-ddns
|
||||
```
|
23
cloudflare-ddns/configs/config.json
Normal file
23
cloudflare-ddns/configs/config.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"cloudflare": [
|
||||
{
|
||||
"authentication": {
|
||||
"api_token": "cloudflare_api_token_here",
|
||||
"api_key": {
|
||||
"api_key": "api_key_if_you_don't_have_a_token",
|
||||
"account_email": "your_email_here_if_you_don't_have_a_token"
|
||||
}
|
||||
},
|
||||
"zone_id": "your_zone_id_here",
|
||||
"subdomains": [
|
||||
"each",
|
||||
"subdomain"
|
||||
],
|
||||
"proxied": false
|
||||
}
|
||||
],
|
||||
"ttl": 120,
|
||||
"a": true,
|
||||
"aaaa": false,
|
||||
"purgeUnknownRecords": false
|
||||
}
|
38
cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh
Normal file
38
cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh
Normal file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
CONTAINER=cloudflare-ddns
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Check if the directory exists
|
||||
if [ ! -d "$DATA_DIR/cloudflare-ddns" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "$DATA_DIR/cloudflare-ddns"
|
||||
echo "Directory '$DATA_DIR/cloudflare-ddns' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '$DATA_DIR/cloudflare-ddns' already exists. Moving on."
|
||||
fi
|
||||
|
||||
# Starts a cloudflare ddns container that is deleted after it is stopped.
|
||||
# All configs stored in /data/cloudflare-ddns
|
||||
if podman container exists "$CONTAINER"; then
|
||||
podman start "$CONTAINER"
|
||||
else
|
||||
podman run -i -d --rm \
|
||||
--net=host \
|
||||
--name "$CONTAINER" \
|
||||
--security-opt=no-new-privileges \
|
||||
-v $DATA_DIR/cloudflare-ddns/config.json:/config.json \
|
||||
timothyjmiller/cloudflare-ddns:latest
|
||||
fi
|
221
cloudflared/README.md
Normal file
221
cloudflared/README.md
Normal file
@ -0,0 +1,221 @@
|
||||
# cloudflared
|
||||
|
||||
## Features
|
||||
|
||||
1. cloudflared tunneling service, aka. Argo Tunnels / Zero Trust / etc
|
||||
2. cloudflared proxy-dns service, provides DNS-over-HTTPS capability for all DNS traffic out from your UDM-SE
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
|
||||
## Configuration
|
||||
|
||||
### cloudflared tunnel
|
||||
|
||||
Configuration is required here, otherwise nothing will work.
|
||||
|
||||
You need to modify `SERVICE_TOKEN` in `51-cloudflared-tunnel.sh` with the secret token you got when configuring the tunnel in Cloudflare Zero Trust
|
||||
|
||||
Run the script and ensure it doesn't error,
|
||||
|
||||
```bash
|
||||
root@UDM-SE:/mnt/data/on_boot.d# ./51-cloudflared-tunnel
|
||||
Hit:1 https://deb.debian.org/debian bullseye InRelease
|
||||
Hit:2 https://download.docker.com/linux/debian bullseye InRelease
|
||||
Hit:3 https://deb.debian.org/debian bullseye-updates InRelease
|
||||
Hit:4 https://pkg.cloudflare.com/cloudflared bullseye InRelease
|
||||
Hit:5 https://security.debian.org/debian-security bullseye-security InRelease
|
||||
Hit:6 https://deb.debian.org/debian bullseye-backports InRelease
|
||||
Hit:7 https://apt.artifacts.ui.com bullseye InRelease
|
||||
Reading package lists... Done
|
||||
Building dependency tree... Done
|
||||
Reading state information... Done
|
||||
All packages are up to date.
|
||||
Reading package lists... Done
|
||||
Building dependency tree... Done
|
||||
Reading state information... Done
|
||||
cloudflared is already the newest version (2023.8.2).
|
||||
Calculating upgrade... Done
|
||||
The following packages were automatically installed and are no longer required:
|
||||
libltdl7 libslirp0 slirp4netns
|
||||
Use 'apt autoremove' to remove them.
|
||||
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
|
||||
root@UDM-SE:/mnt/data/on_boot.d#
|
||||
```
|
||||
|
||||
Now check that the services are healthy,
|
||||
|
||||
```bash
|
||||
root@UDM-SE:~# systemctl status cloudflared.service
|
||||
● cloudflared.service - cloudflared
|
||||
Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; vendor preset: enabled)
|
||||
Active: active (running) since Wed 2023-10-04 15:59:16 AEST; 2h 51min ago
|
||||
Main PID: 6060 (cloudflared)
|
||||
Tasks: 9 (limit: 4724)
|
||||
Memory: 19.8M
|
||||
CPU: 21.886s
|
||||
CGroup: /system.slice/cloudflared.service
|
||||
└─6060 /usr/bin/cloudflared --no-autoupdate tunnel run --token REMOVED
|
||||
|
||||
Oct 04 15:59:16 UDM-SE cloudflared[6060]: 2023-10-04T05:59:16Z INF ICMP proxy will use fe80::d221:f9ff:fe89:c24b in zone eth8 as source for IPv6
|
||||
Oct 04 15:59:16 UDM-SE cloudflared[6060]: 2023-10-04T05:59:16Z WRN The user running cloudflared process has a GID (group ID) that is not within ping_group_range. You might need to add that user to a group within that range, or instead update the range to encompass a group the user is already in by modifying /proc/sys/net/ipv4/ping_group_r>
|
||||
Oct 04 15:59:16 UDM-SE cloudflared[6060]: 2023-10-04T05:59:16Z WRN ICMP proxy feature is disabled error="cannot create ICMPv4 proxy: Group ID 0 is not between ping group 1 to 0 nor ICMPv6 proxy: socket: permission denied"
|
||||
Oct 04 15:59:16 UDM-SE cloudflared[6060]: 2023-10-04T05:59:16Z INF Starting metrics server on 127.0.0.1:38587/metrics
|
||||
Oct 04 15:59:16 UDM-SE cloudflared[6060]: 2023-10-04T05:59:16Z INF Registered tunnel connection connIndex=0 connection=REMOVED event=0 ip=198.41.200.33 location=syd04 protocol=quic
|
||||
Oct 04 15:59:16 UDM-SE systemd[1]: Started cloudflared.
|
||||
Oct 04 15:59:17 UDM-SE cloudflared[6060]: 2023-10-04T05:59:17Z INF Registered tunnel connection connIndex=1 connection=REMOVED event=0 ip=198.41.192.167 location=bne01 protocol=quic
|
||||
Oct 04 15:59:18 UDM-SE cloudflared[6060]: 2023-10-04T05:59:18Z INF Updated to new configuration config=null version=0
|
||||
Oct 04 15:59:18 UDM-SE cloudflared[6060]: 2023-10-04T05:59:18Z INF Registered tunnel connection connIndex=2 connection=REMOVED event=0 ip=198.41.200.23 location=syd07 protocol=quic
|
||||
Oct 04 15:59:19 UDM-SE cloudflared[6060]: 2023-10-04T05:59:19Z INF Registered tunnel connection connIndex=3 connection=REMOVED event=0 ip=198.41.192.67 location=bne01 protocol=quic
|
||||
root@UDM-SE:~#
|
||||
```
|
||||
|
||||
### cloudflared proxy-dns
|
||||
|
||||
Modify the variables in `50-cloudflared-proxy-dns.sh`, the defaults are:
|
||||
|
||||
```bash
|
||||
BIND=127.0.0.53
|
||||
PORT=53
|
||||
UPSTREAM="https://1.1.1.1/dns-query https://1.0.0.1/dns-query"
|
||||
BOOTSTRAP="https://162.159.36.1/dns-query https://162.159.46.1/dns-query https://[2606:4700:4700::1111]/dns-query https://[2606:4700:4700::1001]/dns-query"
|
||||
ARGS="--metrics ${BIND}: --address ${BIND} --port ${PORT}"
|
||||
```
|
||||
|
||||
No configuration is strictly necessary as the above will work and punch DNS requests out thru the default Cloudflare 1.1.1.1/1.0.0.1 resolvers, only over HTTPS.
|
||||
|
||||
You may want to change `UPSTREAM=` if you want to use a different DNS-over-HTTPS resolver.
|
||||
|
||||
For example if you are using Cloudflare Zero Trust Gateway services, there will be a location specific hostname for DNS-over-HTTPS, so you would:
|
||||
|
||||
Change the default variable value of `UPSTREAM="https://1.1.1.1/dns-query https://1.0.0.1/dns-query"`
|
||||
|
||||
To `UPSTREAM="https://UNIQUE_HOSTNAME_FOR_LOCATION.cloudflare-gateway.com/dns-query"`
|
||||
|
||||
Run the script,
|
||||
|
||||
```bash
|
||||
root@UDM-SE:/mnt/data/on_boot.d# ./50-cloudflared-proxy-dns
|
||||
Hit:1 https://deb.debian.org/debian bullseye InRelease
|
||||
Hit:2 https://deb.debian.org/debian bullseye-updates InRelease
|
||||
Hit:3 https://deb.debian.org/debian bullseye-backports InRelease
|
||||
Hit:4 https://download.docker.com/linux/debian bullseye InRelease
|
||||
Get:5 https://security.debian.org/debian-security bullseye-security InRelease [48.4 kB]
|
||||
Hit:6 https://pkg.cloudflare.com/cloudflared bullseye InRelease
|
||||
Hit:7 https://apt.artifacts.ui.com bullseye InRelease
|
||||
Fetched 48.4 kB in 1s (35.4 kB/s)
|
||||
Reading package lists... Done
|
||||
Building dependency tree... Done
|
||||
Reading state information... Done
|
||||
All packages are up to date.
|
||||
Reading package lists... Done
|
||||
Building dependency tree... Done
|
||||
Reading state information... Done
|
||||
cloudflared is already the newest version (2023.8.2).
|
||||
Calculating upgrade... Done
|
||||
The following packages were automatically installed and are no longer required:
|
||||
libltdl7 libslirp0 slirp4netns
|
||||
Use 'apt autoremove' to remove them.
|
||||
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
|
||||
Removed /etc/systemd/system/multi-user.target.wants/cloudflared-proxy-dns.service.
|
||||
removed '/etc/systemd/system/cloudflared-proxy-dns.service'
|
||||
Created symlink /etc/systemd/system/multi-user.target.wants/cloudflared-proxy-dns.service → /etc/systemd/system/cloudflared-proxy-dns.service.
|
||||
root@UDM-SE:/mnt/data/on_boot.d#
|
||||
```
|
||||
|
||||
Now check the status,
|
||||
|
||||
```bash
|
||||
root@UDM-SE:~# systemctl status cloudflared-proxy-dns.service
|
||||
● cloudflared-proxy-dns.service - DNS over HTTPS (DoH) proxy client
|
||||
Loaded: loaded (/etc/systemd/system/cloudflared-proxy-dns.service; enabled; vendor preset: enabled)
|
||||
Active: active (running) since Wed 2023-10-04 15:59:07 AEST; 2h 52min ago
|
||||
Main PID: 4894 (cloudflared)
|
||||
Tasks: 9 (limit: 4724)
|
||||
Memory: 20.0M
|
||||
CPU: 5.701s
|
||||
CGroup: /system.slice/cloudflared-proxy-dns.service
|
||||
└─4894 /usr/bin/cloudflared proxy-dns --metrics 127.0.0.53: --address 127.0.0.53 --port 53 --upstream https://REMOVED.cloudflare-gateway.com/dns-query --bootstrap https://162.159.36.1/dns-query --bootstrap https://162.159.46.1/dns-query --bootstrap https://[2606:4700:4700::1111]/dns-query --bootstrap https://[2606:4700:470>
|
||||
|
||||
Oct 04 15:59:07 UDM-SE systemd[1]: Started DNS over HTTPS (DoH) proxy client.
|
||||
Oct 04 15:59:11 UDM-SE cloudflared[4894]: 2023-10-04T05:59:11Z INF Adding DNS upstream url=https://REMOVED.cloudflare-gateway.com/dns-query
|
||||
Oct 04 15:59:11 UDM-SE cloudflared[4894]: 2023-10-04T05:59:11Z INF Starting metrics server on 127.0.0.53:41219/metrics
|
||||
Oct 04 15:59:11 UDM-SE cloudflared[4894]: 2023-10-04T05:59:11Z INF Starting DNS over HTTPS proxy server address=dns://127.0.0.53:53
|
||||
root@UDM-SE:~#
|
||||
```
|
||||
|
||||
You should also understand what's been done to capture all outbound DNS traffic from both your LAN and your UDM-SE
|
||||
|
||||
A dummy interface named "cloudflared" has been created with an IP of 127.0.0.53/32.
|
||||
|
||||
```bash
|
||||
root@UDM-SE:~# ip addr show dev cloudflared
|
||||
34: cloudflared: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
|
||||
link/ether b6:0f:bb:8e:2e:53 brd ff:ff:ff:ff:ff:ff
|
||||
inet 127.0.0.53/32 scope host cloudflared
|
||||
valid_lft forever preferred_lft forever
|
||||
root@UDM-SE:~#
|
||||
|
||||
root@UDM-SE:~# netstat -tuapn | grep :53 | grep cloudflared
|
||||
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 4894/cloudflared
|
||||
udp 0 0 127.0.0.53:53 0.0.0.0:* 4894/cloudflared
|
||||
root@UDM-SE:~#
|
||||
```
|
||||
|
||||
And that's it at a basic level. dnsmasq has not been modified in any way and the dnsmasq process is still listening on 127.0.0.1:53 (and various other interfaces) which the UDM-SE itself is using as a resolver.
|
||||
|
||||
e.g.
|
||||
|
||||
```bash
|
||||
root@UDM-SE:~# cat /etc/resolv.conf
|
||||
# Generated automatically by ubios-udapi-server
|
||||
nameserver 127.0.0.1
|
||||
root@UDM-SE:~#
|
||||
```
|
||||
|
||||
So your final step, in order to ensure ALL of your local network DNS traffic flows through `cloudflared proxy-dns`, is to reconfigure your upstream Internet connectivity interfaces to use 127.0.0.53
|
||||
|
||||
e.g. in the Unifi UI reconfigure things similar to the below,
|
||||
|
||||

|
||||
|
||||
NOTE: If you have multiple WAN connections, update ALL of them to use 127.0.0.53 as the DNS server for the connection.
|
||||
|
||||
This will result in the following being configured in files on your UDM-SE,
|
||||
|
||||
```bash
|
||||
root@UDM-SE:~# cat /etc/resolv.conf
|
||||
# Generated automatically by ubios-udapi-server
|
||||
nameserver 127.0.0.1
|
||||
root@UDM-SE:~# cat /etc/resolv.dnsmasq
|
||||
# Generated automatically by ubios-udapi-server
|
||||
# static nameservers
|
||||
# eth8
|
||||
nameserver 127.0.0.53
|
||||
root@UDM-SE:~# cat /run/dns.conf.d/resolv.
|
||||
resolv.eth10 resolv.eth7 resolv.eth8 resolv.ppp1
|
||||
root@UDM-SE:~# cat /run/dns.conf.d/resolv.*
|
||||
# Generated automatically by ubios-udapi-server
|
||||
# Generated automatically by ubios-udapi-server
|
||||
# Generated automatically by ubios-udapi-server
|
||||
# static nameservers
|
||||
nameserver 127.0.0.53
|
||||
# Generated automatically by ubios-udapi-server
|
||||
root@UDM-SE:~#
|
||||
```
|
||||
|
||||
What this means is that:
|
||||
|
||||
1. The UnifOS itself resolves via 127.0.0.1:53, which is dnsmasq
|
||||
2. dnsmasq resolves via 127.0.0.53, which is cloudflared, any time the DNS request has to go out to the Internet, *regardless* of which WAN connection will be used, it will route through cloudflared.
|
||||
3. Systems in your networks resolve via UDM-SE IP, which means the dnsmasq process, and then dnsmasq resolves their requests via 127.0.0.1:53, which is cloudflared
|
||||
|
||||
Because of #1 all of your internal DNS aliases/hostnames for your connected devices will continue to work.
|
||||
|
||||
cloudflared will use your active Internet connection to reach the configured resolvers. Note however, that the bootstrap resolvers, which are identified by IP, *MUST* be reachable first.
|
||||
|
||||
`BOOTSTRAP="https://162.159.36.1/dns-query https://162.159.46.1/dns-query https://[2606:4700:4700::1111]/dns-query https://[2606:4700:4700::1001]/dns-query"`
|
||||
|
||||
If all of the above bootstrap resolver IP's are NOT accessible, for example because you have created firewall rules or done anything else to stop connectivity to them working, DNS resolution will probably stop working too.
|
||||
|
75
cloudflared/on_boot.d/50-cloudflared-proxy-dns.sh
Normal file
75
cloudflared/on_boot.d/50-cloudflared-proxy-dns.sh
Normal file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
BIND=127.0.0.53
|
||||
PORT=53
|
||||
UPSTREAM="https://1.1.1.1/dns-query https://1.0.0.1/dns-query"
|
||||
BOOTSTRAP="https://162.159.36.1/dns-query https://162.159.46.1/dns-query https://[2606:4700:4700::1111]/dns-query https://[2606:4700:4700::1001]/dns-query"
|
||||
|
||||
# build argument set, modify this if you want additional customisation
|
||||
ARGS="--metrics ${BIND}: --address ${BIND} --port ${PORT}"
|
||||
|
||||
for i in ${UPSTREAM} ; do
|
||||
ARGS="${ARGS} --upstream $i"
|
||||
done
|
||||
|
||||
for i in ${BOOTSTRAP} ; do
|
||||
ARGS="${ARGS} --bootstrap $i"
|
||||
done
|
||||
|
||||
# ensure this directory exists
|
||||
mkdir -p --mode=0755 /usr/share/keyrings
|
||||
|
||||
if [ ! -f /usr/share/keyrings/cloudflare-main.gpg ] ; then
|
||||
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /etc/apt/sources.list.d/cloudflared.list ] ; then
|
||||
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bullseye main' | tee /etc/apt/sources.list.d/cloudflared.list
|
||||
fi
|
||||
|
||||
dpkg -l | grep cloudflared 1>/dev/null 2>&1
|
||||
|
||||
apt update
|
||||
if [ ${?} != 0 ] ; then
|
||||
# attempt to install
|
||||
apt install -y cloudflared || exit 1
|
||||
else
|
||||
# attempt to upgrade
|
||||
apt upgrade -y cloudflared
|
||||
fi
|
||||
|
||||
systemctl stop cloudflared-proxy-dns.service
|
||||
systemctl disable cloudflared-proxy-dns.service
|
||||
rm -fv /etc/systemd/system/cloudflared-proxy-dns.service
|
||||
systemctl daemon-reload
|
||||
|
||||
# create a dummy interface that cloudflared can listen on, but which will be independent of any Unifi OS related interfaces, including lo which we can't use
|
||||
ifconfig cloudflared 1>/dev/null 2>&1 || ip link add name cloudflared type dummy
|
||||
|
||||
# add our bind IP to the cloudflared interface
|
||||
ip addr show dev cloudflared | grep ${BIND}/32 1>/dev/null 2>&1 || ip addr add ${BIND}/32 dev cloudflared
|
||||
|
||||
tee /etc/systemd/system/cloudflared-proxy-dns.service >/dev/null <<EOF
|
||||
[Unit]
|
||||
Description=DNS over HTTPS (DoH) proxy client
|
||||
Wants=network-online.target nss-lookup.target
|
||||
Before=nss-lookup.target
|
||||
|
||||
[Service]
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
DynamicUser=yes
|
||||
ExecStart=/usr/bin/cloudflared proxy-dns ${ARGS}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable cloudflared-proxy-dns.service
|
||||
systemctl restart cloudflared-proxy-dns.service
|
||||
|
||||
# start the updating service to auto-update the package periodically
|
||||
test -f /etc/systemd/system/cloudflared-update.timer && systemctl enable cloudflared-update.timer
|
||||
|
||||
# EOF
|
39
cloudflared/on_boot.d/51-cloudflared-tunnel.sh
Normal file
39
cloudflared/on_boot.d/51-cloudflared-tunnel.sh
Normal file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this should be the secret tunnel token
|
||||
SERVICE_TOKEN="YOUR SECRET TOKEN GOES HERE"
|
||||
|
||||
# ensure this directory exists
|
||||
mkdir -p --mode=0755 /usr/share/keyrings
|
||||
|
||||
if [ ! -f /usr/share/keyrings/cloudflare-main.gpg ] ; then
|
||||
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f /etc/apt/sources.list.d/cloudflared.list ] ; then
|
||||
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bullseye main' | tee /etc/apt/sources.list.d/cloudflared.list
|
||||
fi
|
||||
|
||||
dpkg -l | grep cloudflared 1>/dev/null 2>&1
|
||||
|
||||
apt update
|
||||
if [ ${?} != 0 ] ; then
|
||||
# attempt to install
|
||||
apt install -y cloudflared || exit 1
|
||||
else
|
||||
# attempt to upgrade
|
||||
apt upgrade -y cloudflared
|
||||
fi
|
||||
|
||||
# only install/overwrite service automatically if the file does not yet exist
|
||||
# this allows you to customise the service and how it operates if necessary
|
||||
test -f /etc/systemd/system/cloudflared.service || cloudflared service install "${SERVICE_TOKEN}"
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable cloudflared.service
|
||||
systemctl restart cloudflared.service
|
||||
|
||||
# start the updating service to auto-update the package periodically
|
||||
test -f /etc/systemd/system/cloudflared-update.timer && systemctl enable cloudflared-update.timer
|
||||
|
||||
# EOF
|
BIN
cloudflared/upstream_dns_explicit.png
Normal file
BIN
cloudflared/upstream_dns_explicit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
157
cni-plugins/05-install-cni-plugins.sh
Normal file
157
cni-plugins/05-install-cni-plugins.sh
Normal file
@ -0,0 +1,157 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
3*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
## Set the version of cni plugin to use. It will revert to latest if an invalid version is given, and the installer will use the last installed version if that fails.
|
||||
# Examples of valid version code would be "latest", "v0.9.1" and "v0.9.0".
|
||||
CNI_PLUGIN_VER=latest
|
||||
# location of the CNI Plugin cached tar files
|
||||
CNI_CACHE="${DATA_DIR}/.cache/cni-plugins"
|
||||
# location of the conf files to go in the net.d folder of the cni-plugin directory
|
||||
CNI_NETD="${DATA_DIR}/podman/cni"
|
||||
# The checksum to use. For CNI Plugin sha1, sha256 and sha512 are available.
|
||||
CNI_CHECKSUM="sha256"
|
||||
# Maximum number of loops to attempt to download the plugin if required - setting a 0 or negative value will reinstalled the currently installed version (if in cache)
|
||||
MAX_TRIES=3
|
||||
|
||||
mkdir -p "${CNI_CACHE}" "${CNI_NETD}" "/etc/cni/net.d"
|
||||
# The script will attempt to use the nominated version first, and falls back to latest version if that fails
|
||||
if [ "$#" -eq 0 ]; then
|
||||
set ${CNI_PLUGIN_VER}
|
||||
fi
|
||||
# Insert conf files for podman networks into the net.d folder
|
||||
populate_netd()
|
||||
{
|
||||
for file in "${CNI_NETD}"/*.conflist
|
||||
do
|
||||
if [ -f "$file" ]; then
|
||||
ln -fs "$file" "/etc/cni/net.d/$(basename "$file")"
|
||||
fi
|
||||
done
|
||||
}
|
||||
# This function checks a valid checksum has been selected. It requires the checksum is given as the first argument
|
||||
checksum_check()
|
||||
{
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "no arguement given"
|
||||
return 2
|
||||
fi
|
||||
case $1 in
|
||||
"sha1" | "sha256" | "sha512")
|
||||
return 0;
|
||||
;;
|
||||
*)
|
||||
echo "Incorrect checksum selection"
|
||||
return 1;
|
||||
;;
|
||||
esac
|
||||
}
|
||||
# Test a file against it's checksum - 1 is the checksum type, 2 is the file to test and 3 is the checksum file
|
||||
checksum_test()
|
||||
{
|
||||
if [ ! -f ${2} ] || [ ! -f ${3} ]; then
|
||||
echo "file does not exist"
|
||||
return 2
|
||||
fi
|
||||
if ! checksum_check ${1}; then
|
||||
echo "An incorrect checksum has been used"
|
||||
return 3
|
||||
fi
|
||||
value1=$(${1}sum ${2} | awk '{print $1}')
|
||||
value2=$(cat ${3} | awk '{print $1}')
|
||||
if [ "${value1}" = "${value2}" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Install function - it requires the first argument to be the version to install
|
||||
install()
|
||||
{
|
||||
if [ "$#" -eq 0 ]; then
|
||||
set "installed"
|
||||
fi
|
||||
if [ -f "${CNI_CACHE}/cni-plugins-linux-arm64-$1.tgz" ]; then
|
||||
echo "Pouring ${CNI_CACHE}/cni-plugins-linux-arm64-$1.tgz"
|
||||
rm -rf /opt/cni/bin
|
||||
mkdir -p /opt/cni/bin
|
||||
tar -xzC /opt/cni/bin -f "${CNI_CACHE}/cni-plugins-linux-arm64-$1.tgz"
|
||||
# Create a link to installed version as fallback option
|
||||
if [ "$1" != "installed" ]; then
|
||||
ln -sf "${CNI_CACHE}/${CNI_TAR}" "${CNI_CACHE}/cni-plugins-linux-arm64-installed.tgz"
|
||||
ln -sf "${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}" "${CNI_CACHE}/cni-plugins-linux-arm64-installed.tgz.${CNI_CHECKSUM}"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
echo "No CNI Plugin available to install"
|
||||
return 1
|
||||
}
|
||||
# Download function - the first argument is the version to download. It will default to latest if a invalid option is given.
|
||||
download()
|
||||
{
|
||||
# To stop infinite recursion
|
||||
if [ ${MAX_TRIES} -lt 1 ]; then
|
||||
# install the last installed version if latest and specified version have both failed.
|
||||
install
|
||||
return 1
|
||||
fi
|
||||
# This defaults to latest, in case the specified download doesn't work.
|
||||
if [ "$#" -eq 0 ]; then
|
||||
set latest
|
||||
fi
|
||||
# Find the corect parameters
|
||||
set "$(basename "$(curl -fsSLo /dev/null -w "%{url_effective}" https://github.com/containernetworking/plugins/releases/$1)")" "$@"
|
||||
CNI_TAR="cni-plugins-linux-arm64-$1.tgz"
|
||||
URL="https://github.com/containernetworking/plugins/releases/download/$1/${CNI_TAR}"
|
||||
# Cache a checksum for the file
|
||||
if [ ! -f "${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}" ]; then
|
||||
echo "Downloading ${URL}.${CNI_CHECKSUM}"
|
||||
curl -fsSLo "/tmp/${CNI_TAR}.${CNI_CHECKSUM}" "${URL}.${CNI_CHECKSUM}"
|
||||
mv "/tmp/${CNI_TAR}.${CNI_CHECKSUM}" "${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}"
|
||||
fi
|
||||
# Cache the tar file
|
||||
if [ ! -f "${CNI_CACHE}/${CNI_TAR}" ]; then
|
||||
echo "Downloading ${URL}"
|
||||
curl -fsSLo "/tmp/${CNI_TAR}" "${URL}"
|
||||
mv "/tmp/${CNI_TAR}" "${CNI_CACHE}/${CNI_TAR}"
|
||||
fi
|
||||
# Symbolic link to latest
|
||||
if [ "$1" != "$2" ]; then
|
||||
ln -sf "${CNI_CACHE}/${CNI_TAR}" "${CNI_CACHE}/cni-plugins-linux-arm64-$2.tgz"
|
||||
ln -sf "${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}" "${CNI_CACHE}/cni-plugins-linux-arm64-$2.tgz.${CNI_CHECKSUM}"
|
||||
fi
|
||||
# Test integrity of the files
|
||||
if ! checksum_test ${CNI_CHECKSUM} ${CNI_CACHE}/${CNI_TAR} ${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}; then
|
||||
echo "Corrupt tar file, deleting tar and checksum"
|
||||
rm -f "${CNI_CACHE}/${CNI_TAR}" "${CNI_CACHE}/${CNI_TAR}.${CNI_CHECKSUM}"
|
||||
MAX_TRIES=${(MAX_TRIES - 1)}
|
||||
# try again on fallback of latest until retries are exhausted
|
||||
download
|
||||
else
|
||||
install $1 $2
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
download
|
||||
populate_netd
|
@ -6,6 +6,7 @@
|
||||
"type": "macvlan",
|
||||
"mode": "bridge",
|
||||
"master": "br5",
|
||||
"mac": "add 3 fake hex portions, replacing x's here 00:1c:b4:xx:xx:xx",
|
||||
"ipam": {
|
||||
"type": "static",
|
||||
"addresses": [
|
||||
|
@ -6,6 +6,7 @@
|
||||
"type": "macvlan",
|
||||
"mode": "bridge",
|
||||
"master": "br5",
|
||||
"mac": "PUT YOUR GENERATED OWN MAC HERE",
|
||||
"ipam": {
|
||||
"type": "static",
|
||||
"addresses": [
|
||||
|
@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
curl -L https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-arm64-v0.8.6.tgz -o /tmp/cni.tgz
|
||||
mkdir -p /mnt/data/podman/cni/
|
||||
tar xf /tmp/cni.tgz -C /mnt/data/podman/cni/
|
||||
rm /tmp/cni.tgz
|
41
container-common/README.md
Normal file
41
container-common/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Container common settings
|
||||
|
||||
## Features
|
||||
|
||||
1. **Stable disk usage footprint**: Sets a maximum log size any podman container log is allowed to grow up to (from unlimited size to 100Mb). Log "max size" is not a hard limit, but a point when Container Monitor attempts to truncate container log file. **NOTE:** application-specific logs that may be written outside container logs are not truncated by Container Monitor at set limits.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have already setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
|
||||
## Customization
|
||||
|
||||
While a 100Mb log limit per container should give plenty of log data for all featured in this repo projects, you can increase or decrease max_log_size value in /data/on_boot.d/05-container-common.sh file after installation.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Run as root on UDM Pro to download and set permissions of on_boot.d script:
|
||||
|
||||
```sh
|
||||
# Download 05-container-common.sh from GitHub
|
||||
curl -L https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/container-common/on_boot.d/05-container-common.sh -o /data/on_boot.d/05-container-common.sh;
|
||||
# Set execute permission
|
||||
chmod a+x /data/on_boot.d/05-container-common.sh;
|
||||
```
|
||||
|
||||
2. Review the script /data/on_boot.d/05-container-common.sh and when happy execute it.
|
||||
|
||||
```sh
|
||||
# Review script
|
||||
cat /data/on_boot.d/05-container-common.sh;
|
||||
# Apply container-common settings
|
||||
/data/on_boot.d/05-container-common.sh;
|
||||
```
|
||||
|
||||
3. Already running containers will pick up new defaults after either container restart ("podman restart \<container-name\>") or after UDM Pro restart. New containers will pick up a change from first run.
|
||||
4. To list containers that are running with log size limits:
|
||||
|
||||
```sh
|
||||
# List container monitor processes with "--log-size-max" custom argument set
|
||||
ps -ef | grep conmon | grep log-size-max
|
||||
```
|
5
container-common/on_boot.d/05-container-common.sh
Normal file
5
container-common/on_boot.d/05-container-common.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# This script runs before any custom containers start to adjust container common defaults
|
||||
|
||||
# Set a limit for container logs. 104857600 Bytes = 100 Megabytes
|
||||
sed -i 's/max_log_size = -1/max_log_size = 104857600/g' /etc/containers/libpod.conf;
|
@ -1,9 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## configuration variables:
|
||||
VLAN=5
|
||||
IPV4_IP="10.0.5.3"
|
||||
# This is the IP address of the container. You may want to set it to match
|
||||
# your own network structure such as 192.168.5.3 or similar.
|
||||
IPV4_GW="10.0.5.1/24"
|
||||
# As above, this should match the gateway of the VLAN for the container
|
||||
# network as above which is usually the .1/24 range of the IPV4_IP
|
||||
|
||||
# if you want IPv6 support, generate a ULA, select an IP for the dns server
|
||||
# and an appropriate gateway address on the same /64 network. Make sure that
|
||||
@ -25,73 +42,65 @@ IPV6_GW=""
|
||||
FORCED_INTFC=""
|
||||
|
||||
# container name; e.g. nextdns, pihole, adguardhome, etc.
|
||||
CONTAINER=nextdns
|
||||
CONTAINER=pihole
|
||||
|
||||
## network configuration and startup:
|
||||
CNI_PATH=/mnt/data/podman/cni
|
||||
if [ ! -f "$CNI_PATH"/macvlan ]; then
|
||||
mkdir -p $CNI_PATH
|
||||
curl -L https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-arm64-v0.8.6.tgz | tar -xz -C $CNI_PATH
|
||||
if ! test -f /opt/cni/bin/macvlan; then
|
||||
echo "Error: CNI plugins not found. You can install it with the following command:" >&2
|
||||
echo " curl -fsSLo ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p /opt/cni
|
||||
rm -f /opt/cni/bin
|
||||
ln -s $CNI_PATH /opt/cni/bin
|
||||
|
||||
for file in "$CNI_PATH"/*.conflist
|
||||
do
|
||||
if [ -f "$file" ]; then
|
||||
ln -s "$file" "/etc/cni/net.d/$(basename "$file")"
|
||||
fi
|
||||
done
|
||||
|
||||
# set VLAN bridge promiscuous
|
||||
ip link set br${VLAN} promisc on
|
||||
ip link set "br${VLAN}" promisc on
|
||||
|
||||
# create macvlan bridge and add IPv4 IP
|
||||
ip link add br${VLAN}.mac link br${VLAN} type macvlan mode bridge
|
||||
ip addr add ${IPV4_GW} dev br${VLAN}.mac noprefixroute
|
||||
ip link add "br${VLAN}.mac" link "br${VLAN}" type macvlan mode bridge
|
||||
ip addr add "${IPV4_GW}" dev "br${VLAN}.mac" noprefixroute
|
||||
|
||||
# (optional) add IPv6 IP to VLAN bridge macvlan bridge
|
||||
if [ -n "${IPV6_GW}" ]; then
|
||||
ip -6 addr add ${IPV6_GW} dev br${VLAN}.mac noprefixroute
|
||||
ip -6 addr add "${IPV6_GW}" dev "br${VLAN}.mac" noprefixroute
|
||||
fi
|
||||
|
||||
# set macvlan bridge promiscuous and bring it up
|
||||
ip link set br${VLAN}.mac promisc on
|
||||
ip link set br${VLAN}.mac up
|
||||
ip link set "br${VLAN}.mac" promisc on
|
||||
ip link set "br${VLAN}.mac" up
|
||||
|
||||
# add IPv4 route to DNS container
|
||||
ip route add ${IPV4_IP}/32 dev br${VLAN}.mac
|
||||
ip route add "${IPV4_IP}/32" dev "br${VLAN}.mac"
|
||||
|
||||
# (optional) add IPv6 route to DNS container
|
||||
if [ -n "${IPV6_IP}" ]; then
|
||||
ip -6 route add ${IPV6_IP}/128 dev br${VLAN}.mac
|
||||
ip -6 route add "${IPV6_IP}/128" dev "br${VLAN}.mac"
|
||||
fi
|
||||
|
||||
# Make DNSMasq listen to the container network for split horizon or conditional forwarding
|
||||
if ! grep -qxF interface=br$VLAN.mac /run/dnsmasq.conf.d/custom.conf; then
|
||||
echo interface=br$VLAN.mac >> /run/dnsmasq.conf.d/custom.conf
|
||||
kill -9 `cat /run/dnsmasq.pid`
|
||||
if ! grep -qxF "interface=br${VLAN}.mac" /run/dnsmasq.conf.d/custom.conf; then
|
||||
echo "interface=br${VLAN}.mac" >>/run/dnsmasq.conf.d/custom.conf
|
||||
kill -9 "$(cat /run/dnsmasq.pid)"
|
||||
fi
|
||||
|
||||
if podman container exists ${CONTAINER}; then
|
||||
podman start ${CONTAINER}
|
||||
if podman container exists "${CONTAINER}"; then
|
||||
podman start "${CONTAINER}"
|
||||
else
|
||||
logger -s -t podman-dns -p ERROR Container $CONTAINER not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up
|
||||
logger -s -t podman-dns -p "ERROR Container ${CONTAINER} not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up"
|
||||
fi
|
||||
|
||||
# (optional) IPv4 force DNS (TCP/UDP 53) through DNS container
|
||||
for intfc in ${FORCED_INTFC}; do
|
||||
if [ -d "/sys/class/net/${intfc}" ]; then
|
||||
for proto in udp tcp; do
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV4_IP} ! -d ${IPV4_IP} --dport 53 -j LOG --log-prefix [DNAT-${intfc}-${proto}]"
|
||||
iptables -t nat -C ${prerouting_rule} 2>/dev/null || iptables -t nat -A ${prerouting_rule}
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV4_IP} ! -d ${IPV4_IP} --dport 53 -j DNAT --to ${IPV4_IP}"
|
||||
iptables -t nat -C ${prerouting_rule} || iptables -t nat -A ${prerouting_rule}
|
||||
|
||||
iptables -t nat -C ${prerouting_rule} 2>/dev/null || iptables -t nat -A ${prerouting_rule}
|
||||
|
||||
# (optional) IPv6 force DNS (TCP/UDP 53) through DNS container
|
||||
if [ -n "${IPV6_IP}" ]; then
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV6_IP} ! -d ${IPV6_IP} --dport 53 -j LOG --log-prefix [DNAT-${intfc}-${proto}]"
|
||||
ip6tables -t nat -C ${prerouting_rule} 2>/dev/null || ip6tables -t nat -A ${prerouting_rule}
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV6_IP} ! -d ${IPV6_IP} --dport 53 -j DNAT --to ${IPV6_IP}"
|
||||
ip6tables -t nat -C ${prerouting_rule} || ip6tables -t nat -A ${prerouting_rule}
|
||||
ip6tables -t nat -C ${prerouting_rule} 2>/dev/null || ip6tables -t nat -A ${prerouting_rule}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
24
haproxy/21-haproxy.conflist
Normal file
24
haproxy/21-haproxy.conflist
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "haproxy",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "macvlan",
|
||||
"mode": "bridge",
|
||||
"master": "br5",
|
||||
"mac": "add 3 fake hex portions, replacing x's here 00:1c:b4:xx:xx:xx",
|
||||
"ipam": {
|
||||
"type": "static",
|
||||
"addresses": [
|
||||
{
|
||||
"address": "10.0.5.3/24",
|
||||
"gateway": "10.0.5.1"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{"dst": "0.0.0.0/0"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
37
haproxy/50-haproxy.sh
Normal file
37
haproxy/50-haproxy.sh
Normal file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
CONTAINER=haproxy
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Check if the directory exists
|
||||
if [ ! -d "${DATA_DIR}/haproxy" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "${DATA_DIR}/haproxy"
|
||||
echo "Directory '${DATA_DIR}/haproxy' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '${DATA_DIR}/haproxy' already exists. Moving on."
|
||||
fi
|
||||
|
||||
# Starts an haproxy container that is deleted after it is stopped.
|
||||
# All configs stored in /data/haproxy
|
||||
if podman container exists "$CONTAINER"; then
|
||||
podman start "$CONTAINER"
|
||||
else
|
||||
podman run -d --net=host --restart always \
|
||||
--name haproxy \
|
||||
--hostname ha.proxy \
|
||||
-v "${DATA_DIR}/haproxy/:/usr/local/etc/haproxy/" \
|
||||
haproxy:latest
|
||||
fi
|
40
haproxy/README.md
Normal file
40
haproxy/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Run haproxy on your UDM
|
||||
|
||||
## Features
|
||||
|
||||
1. Load balance services on your UDM, because why not?.
|
||||
2. Persists through reboots and firmware updates.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
2. You have to have services you want to load-balance, an example would be a multi-master k3s cluster.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Check if you either have `/mnt/data` or `/data/` and adjust below accordingly
|
||||
2. Pull your image with `podman pull docker.io/library/haproxy`.
|
||||
3. Copy [50-haproxy.sh](./50-haproxy.sh) to `/data/on_boot.d/50-haproxy.sh`.
|
||||
4. Choose network configuration - You can run either on the host network or on a seperate docker network. Running on the host network is easier but does mean you can't clash with the ports already in use on the UDM.
|
||||
1. If you want to run on the host network
|
||||
1. You don't have to do anything extra to run on the host network all the instructions / scripts assume this setup.
|
||||
2. If you want to run on a custom docker network do the following:
|
||||
1. Setup the network - there are some instructions in the Customizations setting of the pihole instructions: https://github.com/unifi-utilities/unifios-utilities/tree/main/run-pihole#customizations
|
||||
2. Copy [21-haproxy.conflist](./21-haproxy.conflist) to `/data/podman/cni/` and update its values to reflect your environment.
|
||||
3. Execute the `/data/on_boot.d/05-install-cni-plugins.sh` script to create the network.
|
||||
4. Edit `/data/on_boot.d/50-haproxy.sh` and change `--net=host` to `--network haproxy`
|
||||
5. Create a persistant directory and config for haproxy to use:
|
||||
|
||||
```sh
|
||||
mkdir -p /data/haproxy
|
||||
touch /data/haproxy/haproxy.cfg
|
||||
```
|
||||
|
||||
6. Add your config to `/data/haproxy/haproxy.cfg`. Each configuration is unique, so check out some resouces like [haproxy.com](https://www.haproxy.com/documentation/hapee/latest/configuration/config-sections/) for basics.
|
||||
7. Run `/data/on_boot.d/50-haproxy.sh`
|
||||
|
||||
## Upgrading Easily (if at all)
|
||||
|
||||
1. Edit [update-haproxy.sh](./update-haproxy.sh) to use the same command you used at installation (if changed). If you added your own network config ensure you change the `--net=host` to `--network haproxy`
|
||||
2. Copy the [update-haproxy.sh](./update-haproxy.sh) to `/data/scripts`
|
||||
3. Anytime you want to update your installation, simply run `/data/scripts/update-haproxy.sh`
|
23
haproxy/update-haproxy.sh
Normal file
23
haproxy/update-haproxy.sh
Normal file
@ -0,0 +1,23 @@
|
||||
IMAGE=haproxy:latest
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
podman pull $IMAGE
|
||||
podman stop haproxy
|
||||
podman rm haproxy
|
||||
podman run -d --net=host --restart always \
|
||||
--name haproxy \
|
||||
--hostname ha.proxy \
|
||||
-v "${DATA_DIR}/haproxy/:/usr/local/etc/haproxy/" \
|
||||
$IMAGE
|
BIN
hdhomerun/.DS_Store
vendored
Normal file
BIN
hdhomerun/.DS_Store
vendored
Normal file
Binary file not shown.
62
hdhomerun/README.md
Normal file
62
hdhomerun/README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# HDHomeRun VLAN Traversal
|
||||
|
||||
## License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## Reference
|
||||
|
||||
From https://community.ui.com/questions/Howto-HDHomerun-discovery-on-different-LAN-segment/97db52c6-4add-4ba1-ab0d-27ee6f43db8f
|
||||
|
||||
## Purpose
|
||||
|
||||
The HDHomeRun software sends a UDP broadcast out to the HDHomeRun tuner as part
|
||||
of the discovery process. If your HDHomeRun is on a separate VLAN, you need
|
||||
some sort of proxy to push this UDP broadcast out to the target network.
|
||||
|
||||
Also `socat` is a useful tool and maybe you want to cross-compile it for your
|
||||
UDMP(SE)
|
||||
|
||||
## Compiling `socat`
|
||||
|
||||
In the `build` directory, there is a Docker file to cross compile a socat
|
||||
binary for the Dream Machine Pro.
|
||||
|
||||
```docker build -t build_socat .```
|
||||
```docker run -v $PWD:/tmp/release build_socat```
|
||||
|
||||
The first command builds the container, and the second runs the container. The
|
||||
container will copy the binary inside the container to `/tmp/release`. The -v
|
||||
volume mapping will case the file to apper in the current working directory of
|
||||
the host.
|
||||
|
||||
Precompiled binary is provided. Use at your own risk.
|
||||
|
||||
## Setting up the on.boot script
|
||||
|
||||
1. Update the `99-hdhomerun.sh` script with the IP address of your HDHomeRun
|
||||
tuner.
|
||||
2. Place it in your `on_boot.d` folder and make it executable.
|
||||
3. Reboot your UDMP(SE) or restart the service with something like
|
||||
`systemctl restart udm-boot`
|
||||
4. You can verify the script is running with `ps aux | grep "socat"`
|
||||
5. The HDHomeRun software should now be able to discover the tuner on the
|
||||
other VLAN.
|
||||
|
||||
## Testing
|
||||
|
||||
This was tested with an HDHomeRun PRIME. I do not know if it works with other
|
||||
hardware.
|
BIN
hdhomerun/bin/.DS_Store
vendored
Normal file
BIN
hdhomerun/bin/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
hdhomerun/bin/socat
Executable file
BIN
hdhomerun/bin/socat
Executable file
Binary file not shown.
BIN
hdhomerun/build/.DS_Store
vendored
Normal file
BIN
hdhomerun/build/.DS_Store
vendored
Normal file
Binary file not shown.
43
hdhomerun/build/Dockerfile
Normal file
43
hdhomerun/build/Dockerfile
Normal file
@ -0,0 +1,43 @@
|
||||
# Note: map a volume to /tmp/release to accept the binary.
|
||||
# ```
|
||||
# docker build -t build_socat .
|
||||
|
||||
FROM aarch64/gcc
|
||||
|
||||
ARG SOCAT_VERSION=1.7.4.3
|
||||
ARG READLINE_VERSION=7.0
|
||||
ARG OPENSSL_VERSION=1.0.2k
|
||||
|
||||
# Make directories
|
||||
RUN mkdir -p /build && mkdir -p /tmp/release
|
||||
WORKDIR /build
|
||||
|
||||
# Build readline
|
||||
RUN curl -k -LO ftp://ftp.cwru.edu/pub/bash/readline-${READLINE_VERSION}.tar.gz
|
||||
RUN tar xzvf readline-${READLINE_VERSION}.tar.gz
|
||||
WORKDIR /build/readline-${READLINE_VERSION}
|
||||
RUN ./configure -disable-shared --enable-static -build=aarch64
|
||||
RUN make -j4
|
||||
RUN make install-static
|
||||
|
||||
# Build OpenSSL
|
||||
WORKDIR /build
|
||||
RUN curl -k -LO https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
|
||||
RUN tar zxvf openssl-${OPENSSL_VERSION}.tar.gz
|
||||
WORKDIR /build/openssl-${OPENSSL_VERSION}
|
||||
ENV CFLAGS='-fPIC -static'
|
||||
RUN ./Configure no-shared linux-aarch64
|
||||
RUN make -j4
|
||||
RUN make install
|
||||
|
||||
# Build socat
|
||||
WORKDIR /build
|
||||
RUN curl -k -LO http://www.dest-unreach.org/socat/download/socat-${SOCAT_VERSION}.tar.gz
|
||||
RUN tar xzvf socat-${SOCAT_VERSION}.tar.gz
|
||||
WORKDIR /build/socat-${SOCAT_VERSION}
|
||||
ENV LDFLAGS='-static -ldl -ltinfo'
|
||||
RUN ./configure -build=linux-aarch64
|
||||
RUN make -j4
|
||||
|
||||
# Copy the file to the release directory
|
||||
ENTRYPOINT cp socat /tmp/release
|
29
hdhomerun/on_boot.d/99-hdhomerun.sh
Normal file
29
hdhomerun/on_boot.d/99-hdhomerun.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# Place cross compiled version of `socat` in /data/hdhomerun
|
||||
HDHOMERUN_IP=10.10.30.146
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Check if the directory exists
|
||||
if [ ! -d "$DATA_DIR" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "$DATA_DIR"
|
||||
echo "Directory '$DATA_DIR' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '$DATA_DIR' already exists. Moving on."
|
||||
fi
|
||||
|
||||
${DATA_DIR}/hdhomerun/socat -d -d -v udp4-recvfrom:65001,broadcast,fork udp4-sendto:$HDHOMERUN_IP:65001 &
|
46
homebridge/README.md
Normal file
46
homebridge/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Run Homebridge on your UDM
|
||||
|
||||
### Features
|
||||
|
||||
1. Run [Homebridge](https://homebridge.io/) on your UDM(P).
|
||||
2. Integrate Unifi Protect cameras in HomeKit via `homebridge-unifi-protect`.
|
||||
3. Persists through reboots and firmware updates.
|
||||
|
||||
### Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script).
|
||||
2. You have applied [container-common](https://github.com/unifi-utilities/unifios-utilities/tree/main/container-common) change to prevent UDM storage to fill up with Homebridge logs and addon error messages that can move fast.
|
||||
3. You have applied [cni-plugins](https://github.com/unifi-utilities/unifios-utilities/tree/main/cni-plugins "cni-plugins") to setup for cni configeration. (You dont need the configeration files, just place the script in the on boot folder.)
|
||||
|
||||
### Steps
|
||||
|
||||
1. Type this command: `mkdir -p /data/homebridge/run`
|
||||
2. Copy [25-homebridge.sh](on_boot.d/25-homebridge.sh) to `/data/on_boot.d`. To do this, cd into `/data/on_boot.d`, then type `vim 25-homebridge.sh` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/on_boot.d/25-homebridge.sh "this page") and copy everything using CTRL + A and then CTRL + C and then paste it into vim then click ESC and then type `:x` then click the enter key.
|
||||
3. Copy [90-homebridge.conflist](cni/90-homebridge.conflist) to `/data/podman/cni`. This will create the podman network that bridges the container to your VLAN. To do this, cd into `/data/podman/cni` and type `vim 90-homebridge.conflist` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/cni/90-homebridge.conflist "this page") and the press CTRL + A and then CTRL + C and then paste it into vim and click ESC and then type `:x` then click the enter key.
|
||||
4. Run the Homebridge docker container. Change the timezone (`-e TZ`) to match your timezone, and DNS (`--dns`) to match your VLAN gateway.
|
||||
|
||||
```shell script
|
||||
podman run -d --restart always \
|
||||
--privileged \
|
||||
--name homebridge \
|
||||
--net homebridge \
|
||||
--dns 192.168.1.1 \
|
||||
--dns-search lan \
|
||||
-e TZ=America/Chicago \
|
||||
-e PGID=0 -e PUID=0 \
|
||||
-e HOMEBRIDGE_CONFIG_UI=1 \
|
||||
-e HOMEBRIDGE_CONFIG_UI_PORT=80 \
|
||||
-v "/data/homebridge/:/homebridge/" \
|
||||
-v "/data/homebridge/run/:/run/" \
|
||||
oznu/homebridge:latest
|
||||
```
|
||||
|
||||
5. Access the Homebridge UI based on the IP you assigned, like [http://192.168.1.20/](http://192.168.1.20/).
|
||||
6. If using the UDM Pro, the `homebridge-unifi-protect` plugin can be installed via the Homebridge UI to integrate Unifi Protect cameras.
|
||||
|
||||
### Customization
|
||||
|
||||
- Update [90-homebridge.conflist](cni/90-homebridge.conflist) to match your network:
|
||||
- Change `"bridge": "br0"` to the appropriate VLAN for your network.
|
||||
- Update `"subnet"` and `"gateway"` to match that VLAN.
|
||||
- If you want a specific IP assigned, update `"rangeStart"` and `"rangeEnd"`. Otherwise those properties can be deleted.
|
32
homebridge/cni/90-homebridge.conflist
Normal file
32
homebridge/cni/90-homebridge.conflist
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "homebridge",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "bridge",
|
||||
"bridge": "br0",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"ranges": [
|
||||
[
|
||||
{
|
||||
"subnet": "192.168.1.0/24",
|
||||
"rangeStart": "192.168.1.20",
|
||||
"rangeEnd": "192.168.1.20",
|
||||
"gateway": "192.168.1.1"
|
||||
}
|
||||
]
|
||||
],
|
||||
"routes": [
|
||||
{"dst": "0.0.0.0/0"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tuning",
|
||||
"capabilities": {
|
||||
"mac": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
52
homebridge/on_boot.d/25-homebridge.sh
Executable file
52
homebridge/on_boot.d/25-homebridge.sh
Executable file
@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
CONTAINER=homebridge
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## network configuration and startup:
|
||||
CNI_PATH=${DATA_DIR}/podman/cni
|
||||
# Check if the directory exists
|
||||
if [ ! -d "$CNI_PATH" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "$CNI_PATH"
|
||||
echo "Directory '$CNI_PATH' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '$CNI_PATH' already exists. Moving on."
|
||||
fi
|
||||
|
||||
if [ ! -f "$CNI_PATH"/tuning ]; then
|
||||
mkdir -p $CNI_PATH
|
||||
curl -L https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-arm64-v0.9.1.tgz | tar -xz -C $CNI_PATH
|
||||
fi
|
||||
|
||||
mkdir -p /opt/cni
|
||||
rm -f /opt/cni/bin
|
||||
ln -s $CNI_PATH /opt/cni/bin
|
||||
|
||||
for file in "$CNI_PATH"/*.conflist; do
|
||||
if [ -f "$file" ]; then
|
||||
ln -s "$file" "/etc/cni/net.d/$(basename "$file")"
|
||||
fi
|
||||
done
|
||||
|
||||
# Starts the homebridge container on boot.
|
||||
# All configs stored in /data/homebridge
|
||||
|
||||
if podman container exists ${CONTAINER}; then
|
||||
podman start ${CONTAINER}
|
||||
else
|
||||
logger -s -t homebridge -p ERROR Container $CONTAINER not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up
|
||||
fi
|
69
ipt-enable-logs/README.md
Normal file
69
ipt-enable-logs/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Enable log tags on your UDM
|
||||
|
||||
## Features
|
||||
|
||||
If you're used to the Unifi Security Gateway, you may miss the USG log prefixes that allow you to know which rule blocked certain traffic.
|
||||
|
||||
This mod adds logging prefixes to messages from `/var/log/messages` allowing you to trace a particular log message to the respective iptable rule (which is generated from the firewall rules you configure on the Network application, among other things)
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
|
||||
## General idea
|
||||
|
||||
This mod builds a small Go program that modifies the existing iptables to add `--log-prefix` to entries that are defined as loggable through the `-j LOG` directive. The Go program is built in a Docker container local to the UDM.
|
||||
|
||||
Here's an example snippet of an iptable modified by this program:
|
||||
|
||||
```
|
||||
-A UBIOS_WAN_IN_USER -d 192.168.16.10/32 -p udp -m udp --dport 51820 -m conntrack --ctstate NEW -j LOG --log-prefix "[FW-A-WAN_IN_U-3010] "
|
||||
-A UBIOS_WAN_IN_USER -d 192.168.16.10/32 -p udp -m udp --dport 51820 -m conntrack --ctstate NEW -m comment --comment 00000000008589937602 -j RETURN
|
||||
-A UBIOS_WAN_IN_USER -d 192.168.16.10/32 -p udp -m udp --dport 51821 -m conntrack --ctstate NEW -j LOG --log-prefix "[FW-A-WAN_IN_U-3011] "
|
||||
-A UBIOS_WAN_IN_USER -d 192.168.16.10/32 -p udp -m udp --dport 51821 -m conntrack --ctstate NEW -m comment --comment 00000000008589937603 -j RETURN
|
||||
```
|
||||
|
||||
## Steps
|
||||
|
||||
1. Copy [on_boot.d/30-ipt-enable-logs-launch.sh](./on_boot.d/30-ipt-enable-logs-launch.sh) to /data/on_boot.d
|
||||
1. Copy the [scripts/ipt-enable-logs](./scripts/ipt-enable-logs) folder to /data/scripts
|
||||
1. Copy [scripts/ipt-enable-logs.sh](./scripts/ipt-enable-logs.sh) to /data/scripts
|
||||
1. Execute /data/on_boot.d/30-ipt-enable-logs-launch.sh
|
||||
1. Copy [scripts/refresh-iptables.sh](./scripts/refresh-iptables.sh) to /data/scripts
|
||||
|
||||
## Refreshing iptables
|
||||
|
||||
Whenever you update the firewall rules on the Network application, the iptables will be reprovisioned and will need to be reprocessed
|
||||
by calling /data/scripts/refresh-iptables.sh.
|
||||
|
||||
## Looking at logs
|
||||
|
||||
Logs can be followed easily from another machine through SSH by using the following bash functions:
|
||||
|
||||
```shell
|
||||
function logunifijson() {
|
||||
ssh unifi "tail -f /var/log/messages" | \
|
||||
rg "kernel:" | \
|
||||
sed "s/]IN/] IN/" | \
|
||||
jq --unbuffered -R '. | rtrimstr(" ") | split(": ") | {date: (.[0] | split(" ") | .[0:3] | join(" "))} + (.[1] | capture("\\[.+\\] \\[(?<rule>.*)\\].*")) + ((.[1] | capture("\\[.+\\] (?<rest>.*)") | .rest | split(" ") | map(select(startswith("[") == false) | split("=") | {(.[0]): .[1]})) | (reduce .[] as $item ({}; . + $item)))'
|
||||
}
|
||||
|
||||
function logunifi() {
|
||||
logunifijson | jq --unbuffered -r '"\(.date) - \(.rule)\tIN=\(.IN) \t\(.PROTO)\tSRC=\(.SRC)@\(.SPT)\tDST=\(.DST)@\(.DPT)\tLEN=\(.LEN)\t"'
|
||||
}
|
||||
```
|
||||
|
||||
Here's what the output of `logunifi` looks like:
|
||||
|
||||
```
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
Nov 14 10:58:31 - A-LAN_LOCAL_U-2000 IN=br0 TCP SRC=192.168.16.10@55804 DST=192.168.16.1@443 LEN=52
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Thanks a lot to [@opustecnica](https://github.com/opustecnica) for the [initial implementation](https://github.com/opustecnica/public/wiki/UDM-&-UDM-PRO-NOTES) and idea (based on a bash script)!
|
33
ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh
Executable file
33
ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
# Check if the directory exists
|
||||
if [ ! -d "${DATA_DIR}/scripts" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "${DATA_DIR}/scripts"
|
||||
echo "Directory '${DATA_DIR}/scripts' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '${DATA_DIR}/scripts' already exists. Moving on."
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
if ! iptables-save | grep -e '\-A UBIOS_.* \--log-prefix "\[' >/dev/null; then
|
||||
${DATA_DIR}/scripts/ipt-enable-logs.sh | iptables-restore -c
|
||||
else
|
||||
echo "iptables already contains USER log prefixes, ignoring."
|
||||
fi
|
31
ipt-enable-logs/scripts/ipt-enable-logs.sh
Executable file
31
ipt-enable-logs/scripts/ipt-enable-logs.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check if the directory exists
|
||||
if [ ! -d "${DATA_DIR}/scripts" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "${DATA_DIR}/scripts"
|
||||
echo "Directory '${DATA_DIR}/scripts' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '${DATA_DIR}/scripts' already exists. Moving on."
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
docker run -it --rm -v ${DATA_DIR}/scripts/ipt-enable-logs:/src -w /src --network=none golang:1.17.3 go build -v -o /src/ipt-enable-logs /src >&2
|
||||
|
||||
${DATA_DIR}/scripts/ipt-enable-logs/ipt-enable-logs
|
3
ipt-enable-logs/scripts/ipt-enable-logs/go.mod
Normal file
3
ipt-enable-logs/scripts/ipt-enable-logs/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module pedropombeiro.com/ipt-enable-logs
|
||||
|
||||
go 1.17
|
62
ipt-enable-logs/scripts/ipt-enable-logs/main.go
Normal file
62
ipt-enable-logs/scripts/ipt-enable-logs/main.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := exec.Command("iptables-save")
|
||||
outputBytes, err := cmd.Output()
|
||||
if err != nil {
|
||||
_ = fmt.Errorf("Failed to run iptables-save: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
str := string(outputBytes)
|
||||
lines := strings.Split(str, "\n")
|
||||
re := regexp.MustCompile(`-A UBIOS_([A-Z_]+) .* --comment (\d+) -j ([A-Z]+)`)
|
||||
|
||||
for i, line := range lines {
|
||||
if i != 0 {
|
||||
fmt.Println()
|
||||
}
|
||||
if !strings.HasSuffix(line, "-j LOG") {
|
||||
fmt.Print(line)
|
||||
continue
|
||||
}
|
||||
|
||||
matches := re.FindSubmatch([]byte(lines[i+1]))
|
||||
commentNr, err := strconv.Atoi(string(matches[2]))
|
||||
if err != nil {
|
||||
commentNr = 0
|
||||
}
|
||||
actionName := getActionName(string(matches[3]))
|
||||
ruleName := getRuleName(string(matches[1]), commentNr)
|
||||
fmt.Printf(`%s --log-prefix "[FW-%s-%s] "`, line, actionName, ruleName)
|
||||
}
|
||||
}
|
||||
|
||||
func getActionName(action string) string {
|
||||
action = strings.Replace(action, "RETURN", "A", 1)
|
||||
action = strings.Replace(action, "REJECT", "R", 1)
|
||||
action = strings.Replace(action, "DROP", "D", 1)
|
||||
action = strings.Replace(action, "MASQUERADE", "M", 1)
|
||||
|
||||
return action
|
||||
}
|
||||
|
||||
func getRuleName(rule string, commentNr int) string {
|
||||
ruleName := strings.Replace(rule, "PREROUTING", "PRER", 1)
|
||||
ruleName = strings.Replace(ruleName, "POSTROUTING", "POSTR", 1)
|
||||
ruleName = strings.Replace(ruleName, "HOOK", "HK", 1)
|
||||
ruleName = strings.Replace(ruleName, "USER", "U", 1)
|
||||
if commentNr != 0 {
|
||||
ruleName = fmt.Sprintf("%s-%d", ruleName, commentNr & 0xFFFFFFFF)
|
||||
}
|
||||
return ruleName
|
||||
}
|
36
ipt-enable-logs/scripts/refresh-iptables.sh
Executable file
36
ipt-enable-logs/scripts/refresh-iptables.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check if the directory exists
|
||||
if [ ! -d "${DATA_DIR}/on_boot.d" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "${DATA_DIR}/on_boot.d"
|
||||
echo "Directory '${DATA_DIR}/on_boot.d' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '${DATA_DIR}/on_boot.d' already exists. Moving on."
|
||||
fi
|
||||
set -e
|
||||
|
||||
if [ -f ${DATA_DIR}/on_boot.d/10-dns.sh ]; then
|
||||
if ! iptables-save | grep -e '\-A PREROUTING.* \--log-prefix "\[' >/dev/null; then
|
||||
${DATA_DIR}/on_boot.d/10-dns.sh
|
||||
else
|
||||
echo "iptables already contains DNAT log prefixes, ignoring."
|
||||
fi
|
||||
fi
|
||||
|
||||
${DATA_DIR}/on_boot.d/30-ipt-enable-logs-launch.sh
|
16
modern-unix/Makefile
Normal file
16
modern-unix/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
RSYNC_FLAGS ?= -Ravuzh --no-o
|
||||
SCP_FLAGS ?= -O -o LogLevel=Error
|
||||
SSH_FLAGS ?= -o RemoteCommand=none -o LogLevel=error
|
||||
SSH_HOST ?= root@192.168.16.1 # IP address of the UDM in the local network
|
||||
|
||||
.PHONY: push-config
|
||||
push-config:
|
||||
ssh $(SSH_FLAGS) $(SSH_HOST) 'mkdir -p /data/on_boot.d /data/scripts; rm -rf /data/scripts/*.sh'
|
||||
chmod +x ./on_boot.d/*.sh
|
||||
rsync $(RSYNC_FLAGS) ./on_boot.d/ ./scripts/ ./settings/ $(SSH_HOST):/data/
|
||||
|
||||
.PHONY: install-tools
|
||||
install-tools:
|
||||
ssh $(SSH_FLAGS) $(SSH_HOST) /data/scripts/download-tools.sh
|
||||
|
||||
.PHONY: all clean test
|
34
modern-unix/README.md
Normal file
34
modern-unix/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Modern Unix tools for the UDM
|
||||
|
||||
## Features
|
||||
|
||||
[Modern Unix tools](https://github.com/ibraheemdev/modern-unix) to make the UDM shell more pleasant
|
||||
and modern:
|
||||
|
||||
- [bat](https://github.com/sharkdp/bat): A `cat` clone with syntax highlighting and Git integration.
|
||||
- [bottom](https://github.com/ClementTsang/bottom): Yet another cross-platform graphical
|
||||
process/system monitor.
|
||||
- [croc](https://github.com/schollz/croc): Easily and securely send things from one computer to another 🐊 📦
|
||||
- [duf](https://github.com/muesli/duf): A better `df` alternative.
|
||||
- [gping](https://github.com/orf/gping): `ping`, but with a graph.
|
||||
- [ncdu](https://dev.yorhel.nl/ncdu): Ncdu is a disk usage analyzer with an ncurses interface.
|
||||
- [lsd](https://github.com/Peltoche/lsd): The next gen file listing command. Backwards compatible with `ls`.
|
||||
- [xh](https://github.com/ducaale/xh): A friendly and fast tool for sending HTTP requests.
|
||||
It reimplements as much as possible of HTTPie's excellent design, with a focus on improved performance.
|
||||
|
||||
## Demo
|
||||
|
||||
[](https://asciinema.org/a/e2E1x0QilIvOgSy2N4dKSWwJ8)
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
|
||||
## Steps
|
||||
|
||||
1. You may copy the files in `on_boot.d/`, `scripts/`, and `settings/` to `/data/` in the UDM, or you can
|
||||
use the Makefile targets to copy and install the tools from a remote machine:
|
||||
|
||||
```sh
|
||||
make push-config install-tools
|
||||
```
|
31
modern-unix/on_boot.d/10-shell-profile.sh
Executable file
31
modern-unix/on_boot.d/10-shell-profile.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bssh
|
||||
|
||||
## Configure shell profile
|
||||
PROFILE_SOURCE=/data/settings/profile/global.profile.d
|
||||
PROFILE_TARGET=/etc/profile.d
|
||||
|
||||
device_info() {
|
||||
/usr/bin/ubnt-device-info "$1"
|
||||
}
|
||||
|
||||
# Modify login banner (motd)
|
||||
cat > /etc/motd <<EOF
|
||||
Welcome to $(device_info model)!
|
||||
(c) 2010-$(date +%Y) Ubiquiti Inc. | http://www.ui.com
|
||||
|
||||
Model: $(device_info model)
|
||||
Version: $(device_info firmware)
|
||||
MAC Address: $(device_info mac)
|
||||
EOF
|
||||
|
||||
# Extend UbiOS prompt to include useful information
|
||||
cat > /etc/profile.d/prompt.sh <<'EOF'
|
||||
UDM_NAME="$(grep -m 1 '^name:' /data/unifi-core/config/settings.yaml | awk -F: '{ gsub(/^[ \t]+|[ \t]+$/, "", $2); print tolower($2) }')"
|
||||
PROMPT_MAIN="\u@${UDM_NAME}:\w"
|
||||
|
||||
export PS1="[UDM] ${PROMPT_MAIN}${PS1}"
|
||||
EOF
|
||||
|
||||
# Copy all global profile scripts (for all users) from `/data/settings/profile/global.profile.d/` directory
|
||||
mkdir -p ${PROFILE_SOURCE}
|
||||
cp -rf ${PROFILE_SOURCE}/* ${PROFILE_TARGET}
|
6
modern-unix/scripts/colors.sh
Executable file
6
modern-unix/scripts/colors.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
65
modern-unix/scripts/download-tools.sh
Executable file
65
modern-unix/scripts/download-tools.sh
Executable file
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPTS=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
source "${SCRIPTS}/colors.sh"
|
||||
|
||||
printf "${YELLOW}%s${NC}\n" "Installing tools..."
|
||||
|
||||
target_dir="/data/opt"
|
||||
temp_dir="$(mktemp -d)"
|
||||
|
||||
bat_version=0.22.1
|
||||
croc_version=9.6.3
|
||||
duf_version=0.8.1
|
||||
ncdu_version=2.2.1
|
||||
lsd_version=0.23.1
|
||||
xh_version=0.18.0
|
||||
|
||||
function download_and_extract() {
|
||||
printf "${GREEN}%s${NC}\n" "Downloading $1..."
|
||||
filename="$(basename "$1")"
|
||||
wget -q "$1" -O "${temp_dir}/package.${filename##*.}"
|
||||
|
||||
printf "${GREEN}%s${NC}" "Extracting... "
|
||||
if [[ ${filename##*.} == 'zip' ]]; then
|
||||
extract_zip "$2"
|
||||
else
|
||||
extract_tar "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
function extract_zip() {
|
||||
unzip -o -j "${temp_dir}/package.zip" -d "${target_dir}" "$1"
|
||||
rm -f "${temp_dir}/package.zip"
|
||||
}
|
||||
|
||||
function extract_tar() {
|
||||
if [[ $1 == *"/"* ]]; then
|
||||
tar xzvf "${temp_dir}/package.gz" --directory="${target_dir}" --strip-components=1 "$1" --no-same-owner
|
||||
else
|
||||
tar xzvf "${temp_dir}/package.gz" --directory="${target_dir}" "$1" --no-same-owner
|
||||
fi
|
||||
|
||||
rm -f "${temp_dir}/package.*"
|
||||
}
|
||||
|
||||
mkdir -p "${target_dir}"
|
||||
|
||||
archive_name="bat-v${bat_version}-aarch64-unknown-linux-gnu"
|
||||
download_and_extract "https://github.com/sharkdp/bat/releases/download/v${bat_version}/bat-v${bat_version}-aarch64-unknown-linux-gnu.tar.gz" "${archive_name}/bat"
|
||||
download_and_extract "https://github.com/ClementTsang/bottom/releases/latest/download/bottom_aarch64-unknown-linux-musl.tar.gz" btm
|
||||
download_and_extract "https://github.com/schollz/croc/releases/download/v${croc_version}/croc_${croc_version}_Linux-ARM64.tar.gz" croc
|
||||
download_and_extract "https://github.com/muesli/duf/releases/download/v${duf_version}/duf_${duf_version}_linux_arm64.tar.gz" duf
|
||||
download_and_extract "https://github.com/orf/gping/releases/latest/download/gping-aarch64-unknown-linux-musl.tar.gz" gping
|
||||
|
||||
download_and_extract "https://dev.yorhel.nl/download/ncdu-${ncdu_version}-linux-aarch64.tar.gz" ncdu
|
||||
|
||||
archive_name="lsd-${lsd_version}-aarch64-unknown-linux-musl"
|
||||
download_and_extract "https://github.com/Peltoche/lsd/releases/download/${lsd_version}/${archive_name}.tar.gz" "${archive_name}/lsd"
|
||||
archive_name="xh-v${xh_version}-aarch64-unknown-linux-musl"
|
||||
download_and_extract "https://github.com/ducaale/xh/releases/download/v${xh_version}/xh-v${xh_version}-aarch64-unknown-linux-musl.tar.gz" "${archive_name}/xh"
|
||||
|
||||
rm -rf "${temp_dir}"
|
17
modern-unix/settings/profile/global.profile.d/aliases.sh
Executable file
17
modern-unix/settings/profile/global.profile.d/aliases.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
alias ...=../..
|
||||
alias ....=../../..
|
||||
alias .....=../../../..
|
||||
alias ......=../../../../..
|
||||
alias cp='cp -i'
|
||||
alias la='ls -lAFh'
|
||||
alias ll='ls -l'
|
||||
alias md='mkdir -p'
|
||||
alias mkcd='foo(){ mkdir -p "$1"; cd "$1" }; foo'
|
||||
alias mv='mv -i'
|
||||
alias rd=rmdir
|
||||
alias rm='rm -i'
|
||||
alias docker='podman'
|
||||
alias ls='lsd'
|
||||
alias vim='vi'
|
4
modern-unix/settings/profile/global.profile.d/opt.sh
Executable file
4
modern-unix/settings/profile/global.profile.d/opt.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
PATH="/data/opt:$PATH"
|
||||
export PATH
|
84
mosquitto/README.md
Normal file
84
mosquitto/README.md
Normal file
@ -0,0 +1,84 @@
|
||||
# [Eclipse Mosquitto™](https://mosquitto.org) on Ubiquiti Unifi Dream Machine (Pro)
|
||||
|
||||
> Run the MQTT message broker Eclipse Mosquitto™ on your Unifi Dream Machine (Pro).
|
||||
|
||||
## Prerequisities
|
||||
|
||||
- Working **`on_boot.d`** setup (check [unifi-utilities/unifios-utilities#on-boot-script](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script) for instructions)
|
||||
- A VLAN network (you can use one you are already using)
|
||||
|
||||
**Recommended**
|
||||
|
||||
- Use [container-common](../container-common/README.md) to prevent growing disk usage from accumulating logs
|
||||
|
||||
**Optional**
|
||||
|
||||
- Port forwarding, ie. WAN -> [MOSQUITTO_IP] (TCP/1883) if needed
|
||||
|
||||
**Note**
|
||||
Throughout this guide I'm using `VLAN 20` with gateway `10.0.20.1/24` as an example; Mosquitto's IP will be `10.0.20.4`.
|
||||
_Adjust according to your setup._
|
||||
|
||||
## Setup
|
||||
|
||||
1. First, lets create the folder structure we'll be working with.
|
||||
|
||||
`$ mkdir -p /data/mosquitto/config /data/mosquitto/data`
|
||||
|
||||
This is where Mosquitto's configuration file and data ("persistence database"; if enabled) will live.
|
||||
If you're unsure on how to configure mosquitto, use the provided barebone config [`config/mosquitto.conf`](config/mosquitto.conf) to get it initially running.
|
||||
|
||||
2. **Optional:** Customize [`on_boot.d/45-mosquitto.sh`](on_boot.d/45-mosquitto.sh) to your setup and copy to `/data/on_boot.d/`.
|
||||
Most likely you'll need to mark the script as executable, this will do the trick:
|
||||
|
||||
`$ chmod a+x /data/on_boot.d/45-mosquitto.sh`
|
||||
|
||||
3. Then take a loot at [`cni/45-mosquitto.conflist`](cni/45-mosquitto.conflist) and make sure it matches your previously defined configuration; then place it in `/data/podman/cni/`
|
||||
|
||||
4. Run boot script (to create the mosquitto network set it's ip routes)
|
||||
|
||||
`$ sh /data/on_boot.d/45-mosquitto.sh`
|
||||
|
||||
It fail when trying to run the container, but thats okay, its just for setting op needed configuration before initial image run.
|
||||
The script will also create a [minimal configuration](config/mosquitto.conf) for Mosquitto in `/data/mosquitto/config/`, _**only if it doesn't already exist**_.
|
||||
|
||||
> **Note:** You can use this config to get everything started, but I highly recommend securing your instance with authentication (links to the offical documentation & other resources are at the bottom)
|
||||
|
||||
5. Register the container with podman:
|
||||
|
||||
```shell
|
||||
$ podman run -d --network mosquitto \
|
||||
--restart always \
|
||||
--security-opt=no-new-privileges \
|
||||
--name mosquitto \
|
||||
--hostname mosquitto.local \
|
||||
-e "TZ=Europe/Berlin" \
|
||||
-v /data/mosquitto/config/:/mosquitto/config \
|
||||
-v /data/mosquitto/data/:/mosquitto/data \
|
||||
eclipse-mosquitto:latest
|
||||
```
|
||||
|
||||
6. Run boot script again and we are done!
|
||||
|
||||
`$ sh /data/on_boot.d/45-mosquitto.sh`
|
||||
|
||||
> You should now be able to connect with any MQTT client to Mosquitto, in my case `mqtt://10.0.20.4:1883`
|
||||
|
||||
## Commands
|
||||
|
||||
**Updates**
|
||||
To update container image to its latest version, first delete the current container (`$ podman stop mosquitto && podman rm mosquitto`) and follow through setup steps 5. & 6.
|
||||
|
||||
**Logs**
|
||||
If you want to know what mosquitto is doing, run `$ podman logs -f mosquitto` to follow the logs.
|
||||
|
||||
## Relevant Links
|
||||
|
||||
- [Eclipse Mosquitto Homepage](https://mosquitto.org)
|
||||
- [mosquitto.conf man page](https://mosquitto.org/man/mosquitto-conf-5.html)
|
||||
- [Setting up Authentication in Mosquitto MQTT Broker](https://medium.com/@eranda/setting-up-authentication-on-mosquitto-mqtt-broker-de5df2e29afc)
|
||||
- [eclipse-mosquitto on Docker-Hub](https://hub.docker.com/_/eclipse-mosquitto/)
|
||||
|
||||
## Credits
|
||||
|
||||
Huge thanks to @boostchicken for his incredible work on [unifios-utilities](https://github.com/unifi-utilities/unifios-utilities) and all contributors of this repo!
|
32
mosquitto/cni/45-mosquitto.conflist
Normal file
32
mosquitto/cni/45-mosquitto.conflist
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "mosquitto",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "bridge",
|
||||
"bridge": "br20",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"ranges": [
|
||||
[
|
||||
{
|
||||
"subnet": "10.0.20.0/24",
|
||||
"rangeStart": "10.0.20.4",
|
||||
"rangeEnd": "10.0.20.4",
|
||||
"gateway": "10.0.20.1"
|
||||
}
|
||||
]
|
||||
],
|
||||
"routes": [
|
||||
{"dst": "0.0.0.0/0"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tuning",
|
||||
"capabilities": {
|
||||
"mac": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
11
mosquitto/config/mosquitto.conf
Normal file
11
mosquitto/config/mosquitto.conf
Normal file
@ -0,0 +1,11 @@
|
||||
listener 1883
|
||||
allow_anonymous true
|
||||
|
||||
connection_messages true
|
||||
|
||||
persistence true
|
||||
persistence_location /mosquitto/data/
|
||||
|
||||
log_dest stdout
|
||||
log_type debug
|
||||
log_timestamp true
|
85
mosquitto/on_boot.d/45-mosquitto.sh
Executable file
85
mosquitto/on_boot.d/45-mosquitto.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check if the directory exists
|
||||
if [ ! -d "${DATA_DIR}/podman/cni" ]; then
|
||||
# If it does not exist, create the directory
|
||||
mkdir -p "${DATA_DIR}/podman/cni"
|
||||
echo "Directory '${DATA_DIR}/podman/cni' created."
|
||||
else
|
||||
# If it already exists, print a message
|
||||
echo "Directory '${DATA_DIR}/podman/cni' already exists. Moving on."
|
||||
fi
|
||||
## network configuration
|
||||
VLAN_ID=20
|
||||
IPV4_IP_CONTAINER="10.0.20.4"
|
||||
IPV4_IP_GATEWAY="10.0.20.1"
|
||||
CONTAINER_NAME="mosquitto"
|
||||
CONTAINER_CNI_PATH="${DATA_DIR}/podman/cni/45-mosquitto.conflist"
|
||||
|
||||
# make sure cni plugs are installed
|
||||
if ! test -f /opt/cni/bin/macvlan; then
|
||||
echo "Error: CNI plugins not found. You can install it with the following command:" >&2
|
||||
echo " curl -fsSLo ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/bash ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## network configuration and startup
|
||||
if ! test -f $CONTAINER_CNI_PATH; then
|
||||
logger -s -t podman-mosquitto -p ERROR Container network configuration for $CONTAINER_NAME not found, make sure $CONTAINER_CNI_PATH exists
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# link the conflist into live directory
|
||||
ln -fs "$CONTAINER_CNI_PATH" "/etc/cni/net.d/$(basename "$CONTAINER_CNI_PATH")"
|
||||
|
||||
# set VLAN_ID bridge promiscuous
|
||||
ip link set br${VLAN_ID} promisc on
|
||||
|
||||
# create macvlan bridge and add IPv4 IP
|
||||
ip link add br${VLAN_ID}.mac link br${VLAN_ID} type macvlan mode bridge
|
||||
ip addr add ${IPV4_IP_GATEWAY}/24 dev br${VLAN_ID}.mac noprefixroute
|
||||
|
||||
# set macvlan bridge promiscuous and bring it up
|
||||
ip link set br${VLAN_ID}.mac promisc on
|
||||
ip link set br${VLAN_ID}.mac up
|
||||
|
||||
# add IPv4 route to container
|
||||
ip route add ${IPV4_IP_CONTAINER}/32 dev br${VLAN_ID}.mac
|
||||
|
||||
# create basic config if not exist
|
||||
if ! test -f "$DATA_DIR"/mosquitto/config/mosquitto.conf; then
|
||||
mkdir -p "$DATA_DIR"/mosquitto"$DATA_DIR" "$DATA_DIR"/mosquitto/config
|
||||
cat >"$DATA_DIR"/mosquitto/config/mosquitto.conf <<EOF
|
||||
listener 1883
|
||||
allow_anonymous true
|
||||
|
||||
connection_messages true
|
||||
|
||||
persistence true
|
||||
persistence_location /mosquitto/data/
|
||||
|
||||
log_dest stdout
|
||||
log_type debug
|
||||
log_timestamp true
|
||||
EOF
|
||||
fi
|
||||
|
||||
if podman container exists ${CONTAINER_NAME}; then
|
||||
podman start ${CONTAINER_NAME}
|
||||
else
|
||||
logger -s -t podman-mosquitto -p ERROR Container $CONTAINER_NAME not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up
|
||||
fi
|
@ -1,60 +1,64 @@
|
||||
# Run NextDNS on your UDM
|
||||
|
||||
# THIS IS NO LONGER MAINTAINED. VENDOR PROVIDES DIRECT SUPPORT
|
||||
|
||||
## Features
|
||||
|
||||
1. Run NextDNS on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti.
|
||||
1. Run NextDNS on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti.
|
||||
2. Resolves IP addresses handed out by DHCP on the UDM!
|
||||
3. Persists through reboots and firmware updates.
|
||||
4. If you are already using PiHole and want to test NextDNS out, you can just stop your PiHole container and start this one in its place using the same IP/CNI config.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. You have already setup the on boot script described [here](https://github.com/boostchicken/udm-utilities/tree/master/on-boot-script)
|
||||
1. You have already setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script)
|
||||
|
||||
## Customization
|
||||
|
||||
* Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP address of the container.
|
||||
* The NextDNS docker image is not supported by NextDNS. It is built out of this repo. If you make any enhancements please contribute back via a Pull Request.
|
||||
* If you want to inject custom DNS names into NextDNS use --add-host docker commands. The /etc/resolv.conf and /etc/hosts is generated from that and --dns.
|
||||
* Edit [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) and update its values to reflect your environment (specifically the container name)
|
||||
* If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments.
|
||||
- Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP and MAC address of the container.
|
||||
- The NextDNS docker image is not supported by NextDNS. It is built out of this repo. If you make any enhancements please contribute back via a Pull Request.
|
||||
- If you want to inject custom DNS names into NextDNS use --add-host docker commands. The /etc/resolv.conf and /etc/hosts is generated from that and --dns.
|
||||
- Edit [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) and update its values to reflect your environment (specifically the container name)
|
||||
- If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments.
|
||||
|
||||
## Docker
|
||||
|
||||
The official repo is boostchicken/nextdns-udm. Latest will always refer to the latest builds, there are also tags for each NextDNS release (e.g. 1.6.4).
|
||||
The official repo is boostchicken/nextdns. Latest will always refer to the latest builds, there are also tags for each NextDNS release (e.g. 1.6.4).
|
||||
|
||||
The Dockerfile is included, you can build it locally on your UDM if you don't want to pull from Docker Hub or make customizations
|
||||
|
||||
```shell script
|
||||
podman build . -t nextdns-udm:latest
|
||||
```sh
|
||||
podman build . -t nextdns:latest
|
||||
```
|
||||
|
||||
Building from another device is possible. You must have [buildx](https://github.com/docker/buildx/) installed to do cross platform builds. This is useful if you want to mirror to a private repo
|
||||
Building from another device is possible. You must have [buildx](https://github.com/docker/buildx/) installed to do cross platform builds. This is useful if you want to mirror to a private repo
|
||||
|
||||
```shell script
|
||||
docker buildx build --platform linux/arm64/v8 -t nextdns-udm:latest .
|
||||
```sh
|
||||
docker buildx build --platform linux/arm64/v8 -t nextdns:latest .
|
||||
```
|
||||
|
||||
## Steps
|
||||
|
||||
If you have already installed PiHole, skip right to step 6.
|
||||
If you have already installed PiHole, skip right to step 5.
|
||||
|
||||
1. Copy [05-install-cni-plugins.sh](../cni-plugins/05-install-cni-plugins.sh) to /data/on_boot.d
|
||||
1. Execute /data/on_boot.d/05-install-cni-plugins.sh
|
||||
1. On your controller, make a Corporate network with no DHCP server and give it a VLAN. For this example we are using VLAN 5.
|
||||
2. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to /mnt/data/on_boot.d and update its values to reflect your environment
|
||||
3. Execute /mnt/data/on_boot.d/10-dns.sh
|
||||
4. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to /mnt/data/podman/cni. This will create your podman macvlan network
|
||||
5. Create /mnt/data/nextdns and copy [nextdns.conf](udm-files/nextdns.conf) to it.
|
||||
6. Run the NextDNS docker container. Mounting dbus and running in privileged is only required for mDNS. Also, please change the --dns arguments to whatever was provided by NextDNS.
|
||||
1. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to /data/on_boot.d and update its values to reflect your environment
|
||||
1. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to /data/podman/cni. This will create your podman macvlan network
|
||||
1. Execute /data/on_boot.d/[10-dns.sh](../dns-common/on_boot.d/10-dns.sh)
|
||||
1. Create /data/nextdns and copy [nextdns.conf](udm-files/nextdns.conf) to it.
|
||||
1. Run the NextDNS docker container. Mounting dbus and running in privileged is only required for mDNS. Also, please change the --dns arguments to whatever was provided by NextDNS.
|
||||
|
||||
```shell script
|
||||
podman run -d -it --privileged --network dns --restart always \
|
||||
--name nextdns \
|
||||
-v "/mnt/data/nextdns/:/etc/nextdns/" \
|
||||
-v /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket \
|
||||
--mount type=bind,source=/config/dnsmasq.lease,target=/tmp/dnsmasq.leases \
|
||||
--dns=45.90.28.163 --dns=45.90.30.163 \
|
||||
--hostname nextdns \
|
||||
boostchicken/nextdns-udm:latest
|
||||
```
|
||||
```sh
|
||||
podman run -d -it --privileged --network dns --restart always \
|
||||
--name nextdns \
|
||||
-v "/data/nextdns/:/etc/nextdns/" \
|
||||
-v /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket \
|
||||
--mount type=bind,source=/config/dnsmasq.lease,target=/tmp/dnsmasq.leases \
|
||||
--dns=45.90.28.163 --dns=45.90.30.163 \
|
||||
--hostname nextdns \
|
||||
boostchicken/nextdns:latest
|
||||
```
|
||||
|
||||
7. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs.
|
||||
1. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs.
|
||||
|
@ -1,5 +1,5 @@
|
||||
FROM alpine as builder
|
||||
ENV VERSION=1.7.1
|
||||
ENV VERSION=1.37.11
|
||||
LABEL maintainer="John Dorman <dorman@ataxia.cloud>"
|
||||
RUN wget -O /tmp/nextdns.tar.gz https://github.com/nextdns/nextdns/releases/download/v${VERSION}/nextdns_${VERSION}_linux_arm64.tar.gz \
|
||||
&& mkdir /tmp/nextdns && tar zxf /tmp/nextdns.tar.gz -C /tmp/nextdns
|
||||
|
239
nspawn-container/README.md
Normal file
239
nspawn-container/README.md
Normal file
@ -0,0 +1,239 @@
|
||||
# How to Create a Custom Container on UnifiOS 3.x+
|
||||
|
||||
This is a guide that shows you how to create your own container on UnifiOS 3.0+, and how to install custom services in your container (such as pihole or adguard home).
|
||||
|
||||
Starting with UnifiOS 3.0, podman/docker support has been removed due to a kernel change. However, you can still create a container with systemd-nspawn, which is what this guide will focus on.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Instructions](#instructions)
|
||||
* [Step 1. Create the Container](#step-1-create-the-container)
|
||||
* [Step 2. Configure the Container](#step-2-configure-the-container)
|
||||
* [Step 2A. Configure the Container To Use An Isolated MacVLAN Network](#step-2a-configure-the-container-to-use-an-isolated-macvlan-network)
|
||||
* [Step 3. Configure Persistence Across Firmware Updates](#step-3-configure-persistence-across-firmware-updates)
|
||||
* [Step 4. Install Custom Services](#step-4-install-custom-services)
|
||||
2. [FAQ](#faq)
|
||||
|
||||
## Instructions
|
||||
|
||||
### Step 1. Create the Container
|
||||
|
||||
The following commands are all perfomed on the Unifi router in SSH.
|
||||
|
||||
1. We first need to install systemd-container and debootstrap. We will use debootstrap to create a directory with a base debian system, and then use systemd-nspawn to boot the container.
|
||||
|
||||
```sh
|
||||
apt -y install systemd-container debootstrap
|
||||
```
|
||||
|
||||
2. Next, we use debootstrap to create a directory called `debian-custom` with a base debian system in `/data/custom/machines`.
|
||||
|
||||
```sh
|
||||
mkdir -p /data/custom/machines
|
||||
cd /data/custom/machines
|
||||
debootstrap --include=systemd,dbus unstable debian-custom
|
||||
```
|
||||
* This process can take up to 10 minutes to download and install all the packages.
|
||||
* The container folder will be 390MB after installation, but can increase to 1GB+ after installing many services (storage management is up to you).
|
||||
* Note: Instead of debootstrap, you can also use pacstrap or other distributions' tools to create an Arch Linux, Fedora, or other container instead of a debian container (see [examples here](https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#Examples)).
|
||||
|
||||
3. Finally, let's bring up a shell on this container, set the root password, and enable the networking service. Run each command one-by-one.
|
||||
|
||||
```sh
|
||||
systemd-nspawn -M debian-custom -D /data/custom/machines/debian-custom
|
||||
passwd root
|
||||
systemctl enable systemd-networkd
|
||||
echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||
echo "debian-custom" > /etc/hostname
|
||||
exit
|
||||
```
|
||||
|
||||
* The first command should put you in a shell in the container. If it doesn't work, something went wrong.
|
||||
* Note the password will be hidden when you are typing it out in the `passwd root` command, and you will be asked to type it twice.
|
||||
* We also set the default nameserver to 1.1.1.1 in resolv.conf. You can change this to your own DNS or omit this command if you plan to configure the DNS later.
|
||||
* The hostname can be set to whatever you want, here debian-custom is used as an example.
|
||||
|
||||
### Step 2. Configure the Container
|
||||
|
||||
Now that the container is created, let's configure it. Make sure you are back on the host OS and not in the container.
|
||||
|
||||
1. First, we will link the container to `/var/lib/machines` so we can control it with `machinectl`.
|
||||
|
||||
```sh
|
||||
mkdir -p /var/lib/machines
|
||||
ln -s /data/custom/machines/debian-custom /var/lib/machines/
|
||||
```
|
||||
|
||||
2. Next, we will create a `debian-custom.nspawn` file in `/etc/systemd/nspawn` to configure parameters for the container (such as network, bind mounts, etc). Here I use vim to create the file as a personal preference.
|
||||
|
||||
```sh
|
||||
mkdir -p /etc/systemd/nspawn
|
||||
vim /etc/systemd/nspawn/debian-custom.nspawn
|
||||
```
|
||||
|
||||
* For a container that has access to all the host network interfaces and full capabilities to do anything to the system, here is an example nspawn configuration file. Note it is important to set `Boot=on` so systemd boots up inside the container.
|
||||
|
||||
```ini
|
||||
[Exec]
|
||||
Boot=on
|
||||
Capability=all
|
||||
ResolvConf=off
|
||||
|
||||
[Network]
|
||||
Private=off
|
||||
VirtualEthernet=off
|
||||
```
|
||||
|
||||
* For a more isolated container configured with a macvlan bridge, follow [Step 2A](#step-2a-configure-the-container-to-use-an-isolated-macvlan-network) below instead before running the container.
|
||||
* For other options, see the nspawn manpage [here](https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html).
|
||||
|
||||
3. After you've configured your nspawn file, let's boot up the container and see if it works.
|
||||
|
||||
```sh
|
||||
machinectl start debian-custom
|
||||
machinectl enable debian-custom
|
||||
```
|
||||
|
||||
* If the container booted up, you can check `machinectl status debian-custom` for information (hint: press 'q' to exit the status log).
|
||||
* The second enable command will enable the container to start on boot.
|
||||
|
||||
4. Now that the container is running, we should be able to open a shell or login to it.
|
||||
|
||||
* Typing `machinectl shell debian-custom` should open a shell to the machine and bypass login. Typing `exit` in this shell will exit back to the host Unifi OS.
|
||||
* Typing `machinectl login debian-custom` will give you a login prompt like a normal Linux system. In most cases, you can just use `machinectl shell` to bypass the login for easier access. If you do use the login instead of the shell, you can exit the container by holding the `Ctrl` key and pressing the `]` key 3 times.
|
||||
|
||||
5. Now that you have access to your own container, you can install whatever services you want within it like a normal Linux system ([see examples below](#step-4-install-custom-services)). Make sure you ran `machinectl enable debian-custom` so the container starts on boot.
|
||||
|
||||
### Step 2A: Configure the Container to use an Isolated MacVLAN Network
|
||||
|
||||
This configuration is only needed if you want to isolate the container's network with a macvlan bridge. The following steps are all performed on the host OS.
|
||||
|
||||
1. Download the [10-setup-network.sh](scripts/10-setup-network.sh) script to `/data/on_boot.d` and configure it with your VLAN and IPs for your container and gateway. This script will create a brX.mac interface as a gateway bridge for containers to communicate with.
|
||||
|
||||
```sh
|
||||
mkdir -p /data/on_boot.d && cd /data/on_boot.d
|
||||
curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/nspawn/nspawn-container/scripts/10-setup-network.sh
|
||||
vim 10-setup-network.sh
|
||||
```
|
||||
|
||||
* Modify `VLAN` to an existing VLAN network that you want your container to be on. The default is VLAN 5. Make sure this VLAN network is created in Unifi first with a unique subnet and IP (do not use the same IP as you will use for IPV4_IP or IPV4_GW in this script).
|
||||
* Modify `IPV4_GW` to set the gateway interface's IP. The default is 10.0.5.1/24, but you can use whatever subnet you want as long as it's different than any Unifi subnet.
|
||||
* Modify `IPV4_IP` to your preferred container IP. The default is 10.0.5.3, but you can use whatever you want as long as its on the same subnet as the gateway subnet `IPV4_GW`.
|
||||
* Also modify `IPV6_GW` and `IPV6_IP` if you need IPV6 support. Leave them empty for no IPV6 support.
|
||||
|
||||
2. Create or modify your `/etc/systemd/nspawn/debian-custom.nspawn` file with the following parameters. This will tell nspawn to isolate the network and create a macvlan interface in the container from our VLAN bridge. This interface will be called mv-br5.
|
||||
|
||||
```ini
|
||||
[Exec]
|
||||
Boot=on
|
||||
ResolvConf=off
|
||||
|
||||
[Network]
|
||||
MACVLAN=br5
|
||||
```
|
||||
|
||||
* Change br5 to brX where X = VLAN number you used in `10-setup-network.sh`.
|
||||
|
||||
3. Configure your container to set the IP and gateway you defined in `10-setup-network.sh` by creating a network file in the folder `/etc/systemd/network` under your container's directory. Name this file `mv-brX.network` where X = VLAN number you used (e.g. `mv-br5.network`).
|
||||
|
||||
```sh
|
||||
cd /data/custom/machines/debian-custom/etc/systemd/network
|
||||
vim mv-br5.network
|
||||
```
|
||||
|
||||
* The following is an example configuration based on the default settings in `10-setup-network.sh`.
|
||||
|
||||
```ini
|
||||
[Match]
|
||||
Name=mv-br5
|
||||
|
||||
[Network]
|
||||
IPForward=yes
|
||||
Address=10.0.5.3/24
|
||||
Gateway=10.0.5.1
|
||||
Address=fd62:89a2:fda9:e23::3/64
|
||||
Gateway=fd62:89a2:fda9:e23::1
|
||||
```
|
||||
|
||||
* Make sure to change `Name` to the correct VLAN.
|
||||
* Change `Address` and `Gateway` accordingly if you changed the settings in `10-setup-network.sh`.
|
||||
* You can remove the last 2 lines with IPv6 addresses if you don't need IPv6.
|
||||
|
||||
4. Run the `10-setup-network.sh` script, start the container, open a shell on the container, and check the network.
|
||||
|
||||
```sh
|
||||
chmod +x /data/on_boot.d/10-setup-network.sh
|
||||
/data/on_boot.d/10-setup-network.sh
|
||||
machinectl reboot debian-custom
|
||||
machinectl shell debian-custom
|
||||
ip addr show
|
||||
ping -c4 1.1.1.1
|
||||
```
|
||||
|
||||
* You should see the correct IP defined on mv-br5. If no IP has been assigned, make sure you enabled and started the systemd-networkd service and check again: `systemctl enable --now systemd-networkd`
|
||||
* If you still don't see any IP on mv-br5, then double-check you're using the correct VLAN and put the configuration in the correct location. You can also check `journalctl -eu systemd-networkd` for any errors.
|
||||
* If pinging 1.1.1.1 doesn't work from within the container, double-check you set the correct container IP in your 10-setup-network.sh.
|
||||
|
||||
5. The script `10-setup-network.sh` in `/data/on_boot.d` needs to be started on boot.
|
||||
* If you've installed the udm-boot service, it should automatically run any scripts in `/data/on_boot.d` and no further setup is needed.
|
||||
* If you prefer not to use udm-boot and instead use your own systemd boot service, [here is an example systemd service](scripts/setup-network.service) to run this script at boot. Save it to `/etc/systemd/system/setup-network.service` in the host OS (not container) and then enable it with `systemctl enable setup-network`.
|
||||
|
||||
### Step 3: Configure Persistence Across Firmware Updates
|
||||
|
||||
When the firmware is updated, `/data` (which contains our container storage) and `/etc/systemd` (which contains our boot scripts) are preserved, but `/var` and `/usr` is deleted by the firmware update script. Any additional debian packages that are installed in the host OS like systemd-container are also deleted. This means we need to reinstall the systemd-container package and re-link our container to /var/lib/machines (for machinectl access) when the firmware is upgraded. This can be accomplished with a simple boot script that checks to see if this package is installed on boot.
|
||||
|
||||
1. Download the [0-setup-system.sh](scripts/0-setup-system.sh) script into /data/on_boot.d.
|
||||
|
||||
```sh
|
||||
mkdir -p /data/on_boot.d && cd /data/on_boot.d
|
||||
curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/nspawn/nspawn-container/scripts/0-setup-system.sh
|
||||
chmod +x /data/on_boot.d/0-setup-system.sh
|
||||
```
|
||||
|
||||
2. Download the backup dpkg package files for systemd-container and dependencies into `/data/custom/dpkg`. These packages will only be used as a backup install in case the Internet is down after the first boot after an update.
|
||||
|
||||
```sh
|
||||
mkdir -p /data/custom/dpkg && cd /data/custom/dpkg
|
||||
apt download systemd-container libnss-mymachines debootstrap arch-test
|
||||
```
|
||||
|
||||
3. The script `0-setup-system.sh` in `/data/on_boot.d` needs to be started on boot.
|
||||
* If you've installed the udm-boot service, it should automatically run any scripts in `/data/on_boot.d` and no further setup is needed.
|
||||
* If you prefer not to use udm-boot and instead use your own systemd boot service, [here is an example systemd service](scripts/setup-system.service) to run this script at boot. Save it to `/etc/systemd/system/setup-system.service` in the host OS (not container) and then enable it with `systemctl enable setup-system`.
|
||||
|
||||
### Step 4: Install Custom Services
|
||||
|
||||
Services can be installed in the container like any linux system. For debian containers, you can use apt or other manual methods. Follow the Debian/Linux guide for your particular software that you want to install.
|
||||
|
||||
* Common examples
|
||||
* [Pi-Hole](examples/pihole/README.md)
|
||||
* [AdGuard Home](examples/adguardhome/README.md)
|
||||
|
||||
## FAQ
|
||||
|
||||
1. How do I access a folder from the host OS in the container (e.g. the /data directory)?
|
||||
|
||||
* Edit your `.nspawn` config file and add the following `[Files]` section. You can specify multiple `Bind=` or `BindReadOnly=` lines to bind mount multiple directories. See [nspawn manpage](https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html#Bind=) for more details.
|
||||
|
||||
```ini
|
||||
[Files]
|
||||
Bind=/data:/data
|
||||
```
|
||||
|
||||
2. I am getting security errors trying to run certain privileged commands in the container.
|
||||
|
||||
* Edit your `.nspawn` config file and add `Capability=all` under the `[Exec]` section to unlock all security capablitlites. You can also permit or restrict capabilities for enhanced security (see the [nspawn manpage](https://www.freedesktop.org/software/systemd/man/systemd.nspawn.html#Capability=) for more information).
|
||||
|
||||
3. Some programs complain of a missing /lib/modules folder and can't access kernel modules.
|
||||
|
||||
* Edit your `.nspawn` config file and add `BindReadOnly=/lib/modules` to the `[Files]` section. This will bind mount the /lib/modules folder from the host OS. You might also want to try unlocking all capabilitites or specific ones (as in the above question) if you're still having issues with permissions using certain modules.
|
||||
|
||||
4. iptables doesn't work in the container after I installed it.
|
||||
|
||||
* You need to use iptables-legacy and not iptables-nft because the host OS is still using the legacy iptables. If using a Debian container, you can switch to the legacy iptables with the following commands executed from within the container. Also, you won't be able to see or modify the host's iptables entries if you're using a private/macvlan network for the container.
|
||||
|
||||
```sh
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy
|
||||
update-alternatives --set ip6tables /usr/bin/ip6tables-legacy
|
||||
```
|
||||
|
22
nspawn-container/examples/adguardhome/README.md
Normal file
22
nspawn-container/examples/adguardhome/README.md
Normal file
@ -0,0 +1,22 @@
|
||||
## How to Install AdGuard Home in Container
|
||||
|
||||
This guide assumes you have already created and started an nspawn container as instructed in the [main README](../../README.md), and have configured an isolated macvlan network for your container.
|
||||
|
||||
To install AdGuard Home, we simply run the automated install as instructed in the [AdGuard Home documentation](https://github.com/AdguardTeam/AdGuardHome#automated-install-unix).
|
||||
|
||||
1. Spawn a shell to your container.
|
||||
|
||||
```sh
|
||||
machinectl shell debian-custom
|
||||
```
|
||||
|
||||
2. Run the automated install command from the adguard documentation and follow the prompts. Refer to the pihole documentation for more details.
|
||||
|
||||
```sh
|
||||
apt -y install curl
|
||||
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
|
||||
```
|
||||
|
||||
3. Go to http://10.0.5.3:3000 to configure AdGuard Home (or whatever IP you configured for your container).
|
||||
4. After configuration, you can access Ad Guard Home web gui at http://10.0.5.3.
|
||||
5. Now you can set your LAN clients to use the AdGuard Home IP 10.0.5.3 as the DNS, or use dig to test DNS resolution from a client (e.g.: `dig @10.0.5.3 google.com A`).
|
149
nspawn-container/examples/multicast-relay/README.md
Normal file
149
nspawn-container/examples/multicast-relay/README.md
Normal file
@ -0,0 +1,149 @@
|
||||
## Create the filesystem overlay
|
||||
|
||||
If you're going to create several nspawn containers, you can save some disk
|
||||
space by using overlayfs to use a common base. Follow the instructions in the
|
||||
unifi-utilities [documentation](https://github.com/unifi-utilities/unifios-utilities/blob/main/nspawn-container/README.md)
|
||||
for UnifiOS 3.0+ containers. I called my container `debian-base`.
|
||||
|
||||
Next, we need an `upperdir` where the file changes are saved and a `workdir`
|
||||
where temporary file changes are saved. I'm going to create a container for
|
||||
multicast-relay, replacing the [podman container](https://github.com/scyto/multicast-relay)
|
||||
that I used prior to 3.x. An important note is that upperdir and workdir
|
||||
must not be on the overlayfs that UnifiOS uses. I opted to store this data
|
||||
on the hard drive that I use for video storage at `/volume1`.
|
||||
|
||||
So, we have the following directories, which you need to create:
|
||||
|
||||
- `/var/lib/machines/multicast-relay`: This will be the root directory of
|
||||
our new container.
|
||||
- `/volume1/machines/multicast-relay/upper`: This stores the differences from
|
||||
the base container.
|
||||
- `/volume1/machines/multicast-relay/work`: This is a temporary directory for
|
||||
changes before they're saved to `upper`. This could possibly be on a `tmpfs`
|
||||
mount, but I didn't want to mess with available memory.
|
||||
- `/data/custom/machines/debian-base`: This is the base container directory
|
||||
created by following the README linked above.
|
||||
|
||||
Do it:
|
||||
```shell
|
||||
mkdir -p /var/lib/machines/multicast-relay /volume1/machines/multicast-relay/{upper,work}
|
||||
```
|
||||
|
||||
Now add the matching entry to your fstab. I'm not 100% sure how permanent this is,
|
||||
but I'll find out when I either reboot or do a firmware upgrade.
|
||||
|
||||
Append this to `/etc/fstab`
|
||||
```
|
||||
overlay /var/lib/machines/multicast-relay overlay noauto,x-systemd.automount,lowerdir=/data/custom/machines/debian-base,upperdir=/volume1/machines/multicast-relay/upper,workdir=/volume1/machines/multicast-relay/work 0 0
|
||||
```
|
||||
|
||||
If everything is good, you can `mount /var/lib/machines/multicast-relay`. If
|
||||
there's any error from that, you have some homework to do. This _should_ automount
|
||||
on reboot, but I haven't tested by rebooting my UDM Pro yet. We'll see 🤞.
|
||||
|
||||
## Configure the container
|
||||
|
||||
With your overlay in place, you can start the container and install your stuff.
|
||||
```
|
||||
systemd-nspawn -M multicast-relay -D /var/lib/machines/multicast-relay
|
||||
```
|
||||
|
||||
You should now be at a root shell inside the container. I configured this all
|
||||
manually, but you can use the [script](./configure-container.sh) I created during
|
||||
my trial and error to save yourself some time. Minimal Debian doesn't have
|
||||
`curl` or `wget`, so you can install one of those and download the script,
|
||||
or copy-paste into `vi` or something. This is left as an exercise to the reader.
|
||||
|
||||
To escape this container, you'll have to press the cheat code given at the start
|
||||
of your session. (HINT: Press <kbd>Ctrl</kbd> + <kbd>]</kbd> 3 times.)
|
||||
|
||||
NOTE: I didn't set the root password, which you will see in many tutorials. It
|
||||
isn't needed. The host can bypass any login prompt using `machinectl shell <container>`.
|
||||
You might want to set a root password and/or other user if you are using the
|
||||
container as a lightweight VM.
|
||||
|
||||
## Run the container
|
||||
|
||||
If this is your first systemd-nspawn service, you'll need to create the config
|
||||
directory.
|
||||
|
||||
```
|
||||
mkdir -p /etc/systemd/nspawn
|
||||
```
|
||||
|
||||
Now create the container launch configuration in the file indicated. `multicast-relay`
|
||||
requires the ability to open raw sockets, so we grant that capability and strip the rest. Be sure you specify the interfaces you wish to use in the `Environment=` line.
|
||||
Optionally, you can specify additional `multicast-relay` options in `OPTS`
|
||||
|
||||
```
|
||||
# /etc/systemd/nspawn/multicast-relay.nspawn
|
||||
[Exec]
|
||||
Boot=on
|
||||
Capability=CAP_NET_RAW
|
||||
ResolvConf=off
|
||||
Environment=INTERFACES="br0 br50"
|
||||
Environment=OPTS=
|
||||
|
||||
[Network]
|
||||
Private=off
|
||||
VirtualEthernet=off
|
||||
```
|
||||
|
||||
Once that file is in place, you're ready to enable the container on boot and run it.
|
||||
|
||||
```
|
||||
machinectl enable multicast-relay
|
||||
machinectl start multicast-relay
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
You can view the stdout of the container in the host journal.
|
||||
|
||||
```
|
||||
journalctl -xe
|
||||
```
|
||||
|
||||
Output from multicast-relay itself won't be found here though. You _should_ be
|
||||
able to view a containers journal from the host, but I got an error when I tried
|
||||
suggesting the Debian container has a newer journal format than the UnifiOS host.
|
||||
|
||||
No matter, you can just enter the container and get a root shell (no login required).
|
||||
|
||||
```
|
||||
machinectl shell multicast-relay
|
||||
```
|
||||
|
||||
Now, we're setting the interface and options via environment variables set on the
|
||||
host. If you want to double check that's working correctly, check the environment
|
||||
of systemd from within the container.
|
||||
|
||||
```
|
||||
cat /proc/1/environ | tr '\0' '\n'
|
||||
```
|
||||
output:
|
||||
```
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
container=systemd-nspawn
|
||||
HOME=/root
|
||||
USER=root
|
||||
LOGNAME=root
|
||||
container_uuid=c05b41ce-0995-412d-bd2d-338759b24e54
|
||||
NOTIFY_SOCKET=/run/host/notify
|
||||
container_host_version_id=11
|
||||
container_host_id=debian
|
||||
INTERFACES=br0 br50
|
||||
```
|
||||
|
||||
You could use the same command to view the environment of our service. In this case,
|
||||
we can use the PID of `dash`, the shell script interpreter from `start.sh`.
|
||||
|
||||
```
|
||||
root@DreamMachinePro:~# cat /proc/$(pidof dash)/environ | tr '\0' '\n'
|
||||
LANG=C.UTF-8
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
INVOCATION_ID=d1cfaf43a00b4e79bcddca6a1595837c
|
||||
JOURNAL_STREAM=8:51317778
|
||||
SYSTEMD_EXEC_PID=47
|
||||
INTERFACES=br0 br50
|
||||
```
|
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install dependencies
|
||||
apt install -y --no-install-recommends python3 python3-netifaces git ca-certificates
|
||||
|
||||
# Checkout latest commit of default branch of multicast-relay
|
||||
cd /opt
|
||||
git clone --depth=1 https://github.com/alsmith/multicast-relay.git
|
||||
|
||||
# Drop a startup script
|
||||
cat <<'EOF' | tee /opt/multicast-relay/start.sh
|
||||
#!/bin/dash
|
||||
# This script adapted from scyto
|
||||
# https://github.com/scyto/multicast-relay/blob/master/start.sh
|
||||
SCRIPT_DIR=$(dirname $(readlink -f $0))
|
||||
|
||||
echo "starting multicast-relay"
|
||||
echo "Using Interfaces: ${INTERFACES}"
|
||||
echo "Using Options --foreground " $OPTS
|
||||
python3 "${SCRIPT_DIR}/multicast-relay.py" --interfaces ${INTERFACES} --foreground $OPTS
|
||||
EOF
|
||||
|
||||
chmod +x /opt/multicast-relay/start.sh
|
||||
|
||||
# Install and enable a systemd service
|
||||
cat <<'EOF' | tee /etc/systemd/system/multicast-relay.service
|
||||
[Unit]
|
||||
Description=multicast relay service
|
||||
|
||||
[Service]
|
||||
PassEnvironment=INTERFACES OPTS
|
||||
ExecStart=/opt/multicast-relay/start.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl enable multicast-relay.service
|
48
nspawn-container/examples/pihole/README.md
Normal file
48
nspawn-container/examples/pihole/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
## How to Install Pi-Hole in Container
|
||||
|
||||
This guide assumes you have already created and started an nspawn container as instructed in the [main README](../../README.md), and have configured an isolated macvlan network for your container.
|
||||
|
||||
To install pihole, we simply run the automated install as instructed in the [pihole documentation](https://docs.pi-hole.net/main/basic-install/) and follow the prompts.
|
||||
|
||||
|
||||
1. Spawn a shell to your container.
|
||||
|
||||
```sh
|
||||
machinectl shell debian-custom
|
||||
```
|
||||
|
||||
2. Run the automated install command from the pihole documentation and follow the prompts. Refer to the pihole documentation for more details.
|
||||
|
||||
```sh
|
||||
apt -y install curl
|
||||
curl -sSL https://install.pi-hole.net | PIHOLE_SKIP_OS_CHECK=true bash
|
||||
```
|
||||
|
||||
* You must use `PIHOLE_SKIP_OS_CHECK=true` so pihole can be installed on Debian unstable.
|
||||
* After installation, the debian-custom container has a size of 611 MB after running `apt clean` to delete the package cache.
|
||||
|
||||
3. When the install says a static IP is needed, press Continue.
|
||||
4. Select an upstream DNS provider on the next page, or add your custom DNS provider. Note all these options can be changed later in the admin panel, so you don't need to be perfect here.
|
||||
5. On the next page, choose "Yes" to include the default list or "No" to not include any block lists at install (you will have to install your own later in that case).
|
||||
6. On the next page, choose "Yes" to install the Admin web interface, then "Yes" on the next page to install the default web server that pihole uses (lighthttpd). It's also possible to use nginx instead of lighthttpd, but this isn't covered in this tutorial.
|
||||
7. On the next two pages, click Yes to enable Query Logging, and enable "Show everything". You can disable query logging or hide information from the log if you prefer.
|
||||
8. Once the install is finished, it will tell you what your pihole IP and admin password is.
|
||||
9. You can either use the current admin password the installation gave you, or run `pihole -a -p` to update the password.
|
||||
10. You should now be able to access the pihole admin page at https://10.0.5.3/admin if you used the default container IP.
|
||||
11. As a final step, you need to set "Permit all origins" in the Pi-Hole Admin to allow requests from more than one hop away (i.e. your LAN clients). Go to Pi-Hole Admin -> Settings -> DNS -> Permit all origins -> Save.
|
||||
12. Now you can set your LAN clients to use the pihole IP 10.0.5.3 as the DNS, or use dig to test DNS resolution from a client (e.g.: `dig @10.0.5.3 google.com A`).
|
||||
|
||||
## How to Update or Reconfigure Pi-Hole.
|
||||
|
||||
To update pihole, simply run the following from within the container.
|
||||
|
||||
```sh
|
||||
PIHOLE_SKIP_OS_CHECK=true pihole -up
|
||||
```
|
||||
|
||||
In case there is a configuration error and pihole is having trouble, you can reconfigure it from scratch by running:
|
||||
|
||||
|
||||
```sh
|
||||
PIHOLE_SKIP_OS_CHECK=true pihole -r
|
||||
```
|
280
nspawn-container/interactive_setup.sh
Normal file
280
nspawn-container/interactive_setup.sh
Normal file
@ -0,0 +1,280 @@
|
||||
#!/bin/bash
|
||||
|
||||
###################################################################
|
||||
#Script Name : interactive_setup
|
||||
#Description : This script guides you through creating a custom container on UnifiOS 3.0+ using systemd-nspawn.
|
||||
# It includes steps for configuring the container, ensuring persistence across firmware updates,
|
||||
# and installing custom services such as pihole (Not Yet) or adguard home.
|
||||
# The process involves installing systemd-container and debootstrap and using them to create
|
||||
# a base debian system in /data/custom/machines directory.
|
||||
#Author : Apo-mak
|
||||
#Last Date Edited : 09-06-2023
|
||||
###################################################################
|
||||
|
||||
set -e
|
||||
|
||||
container_name="debian-custom"
|
||||
container_root_pasword="12345678"
|
||||
|
||||
vlan_id="5"
|
||||
vlan_address="10.0.5.3/24"
|
||||
vlan_gateway="10.0.5.1"
|
||||
|
||||
##
|
||||
# Color Variables
|
||||
##
|
||||
green='\e[32m'
|
||||
blue='\e[34m'
|
||||
clear='\e[0m'
|
||||
|
||||
##
|
||||
# Color Functions
|
||||
##
|
||||
|
||||
ColorGreen(){
|
||||
echo -ne $green$1$clear
|
||||
}
|
||||
ColorBlue(){
|
||||
echo -ne $blue$1$clear
|
||||
}
|
||||
|
||||
##############################################
|
||||
function set_variables(){
|
||||
read -p "Enter the container name [$container_name]: " container_name
|
||||
container_name=${container_name:-"debian-custom"}
|
||||
read -p "Enter the container root password [$container_root_pasword]: " container_root_pasword
|
||||
container_root_pasword=${container_root_pasword:-"12345678"}
|
||||
}
|
||||
|
||||
function set_container_network_variables(){
|
||||
read -p "Enter the container vlan_id [$vlan_id]: " vlan_id
|
||||
vlan_id=${vlan_id:-"5"}
|
||||
read -p "Enter the container vlan_address [$vlan_address]: " vlan_address
|
||||
vlan_address=${vlan_address:-"10.0.5.3/24"}
|
||||
read -p "Enter the container vlan_gateway [$vlan_gateway]: " vlan_gateway
|
||||
vlan_gateway=${vlan_gateway:-"10.0.5.1"}
|
||||
}
|
||||
|
||||
function echo_variables(){
|
||||
echo "#### Printing set Variables: ###"
|
||||
echo "Container Name: $container_name "
|
||||
echo "Container Root Password: $container_root_pasword "
|
||||
|
||||
echo "Network Vlan ID: $vlan_id "
|
||||
echo "Container $vlan_address "
|
||||
echo "Network Getway: $vlan_gateway "
|
||||
|
||||
}
|
||||
|
||||
function create_custom_container_simple(){
|
||||
echo "You have selected to setup a container that has access to all the host network
|
||||
interfaces and full capabilities to do anything to the system"
|
||||
read -p "Press enter to continue OR ctrl + c to cancel."
|
||||
create_custom_container ;
|
||||
setup_networking_simple ;
|
||||
setup_persistence ;
|
||||
setup_backup_dpkg_files
|
||||
}
|
||||
|
||||
function create_custom_container_macvlan(){
|
||||
echo "You have selected to setup a container to use an Isolated MacVLAN Network AKA Vlan."
|
||||
read -p "Press enter to continue OR ctrl + c to cancel."
|
||||
create_custom_container ;
|
||||
setup_networking_MACVLAN ;
|
||||
setup_persistence ;
|
||||
setup_backup_dpkg_files
|
||||
}
|
||||
|
||||
|
||||
function create_custom_container() {
|
||||
echo ""
|
||||
echo " Creating a Custom Container on UnifiOS 3.x"
|
||||
echo ""
|
||||
|
||||
#### check if directory exists and abort
|
||||
|
||||
if [ -d "/data/custom/machines/$container_name" ]
|
||||
then
|
||||
echo "Directory /data/custom/machines/$container_name already exists... aborting the setup ...
|
||||
try manual setup or setup with new container name."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Step 1. Create the Container
|
||||
echo " Installing the systemd-container and debootstrap"
|
||||
apt -y install systemd-container debootstrap
|
||||
|
||||
### create a directory called "$container_name" with a base debian system in /data/custom/machines
|
||||
echo "Creating container required directories"
|
||||
mkdir -p /data/custom/machines
|
||||
cd /data/custom/machines
|
||||
debootstrap --include=systemd,dbus unstable "$container_name"
|
||||
|
||||
### Finally, let's bring up a shell on this container
|
||||
echo "Set container Root password, Network setting and enable systemd-networkd"
|
||||
#systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name"
|
||||
#systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name" echo "This Echo is from inside the new Container ..."
|
||||
systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name" /bin/bash -c "echo 'root:${container_root_pasword}' | chpasswd"
|
||||
|
||||
echo "In container start network"
|
||||
systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name" /bin/bash -c systemctl enable systemd-networkd
|
||||
|
||||
echo "in container set default DNS 1.1.1.1"
|
||||
systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name" /bin/bash -c echo "nameserver 1.1.1.1" > /etc/resolv.conf \
|
||||
echo ""$container_name"" > /etc/hostname
|
||||
|
||||
#### we will link the container to /var/lib/machines so we can control it with machinectl
|
||||
echo "Linking the container to /var/lib/machines"
|
||||
mkdir -p /var/lib/machines
|
||||
ln -s /data/custom/machines/"$container_name" /var/lib/machines/
|
||||
|
||||
}
|
||||
|
||||
function setup_networking_simple() {
|
||||
echo ""
|
||||
echo " Setting up networking Simple"
|
||||
echo ""
|
||||
##### we will create a "$container_name".nspawn file in /etc/systemd/nspawn to configure parameters for the container
|
||||
######(such as network, bind mounts, etc)
|
||||
echo "configuring parameters for the container "
|
||||
mkdir -p /etc/systemd/nspawn
|
||||
|
||||
cat <<EOF > /etc/systemd/nspawn/"$container_name".nspawn
|
||||
[Exec]
|
||||
Boot=on
|
||||
Capability=all
|
||||
|
||||
[Network]
|
||||
Private=off
|
||||
VirtualEthernet=off
|
||||
ResolvConf=off
|
||||
EOF
|
||||
}
|
||||
|
||||
function setup_networking_MACVLAN() {
|
||||
echo ""
|
||||
echo " Setting up networking MACVLAN"
|
||||
echo ""
|
||||
#####we will create a "$container_name".nspawn file in /etc/systemd/nspawn to configure parameters for the container
|
||||
######(such as network, bind mounts, etc)
|
||||
echo "configuring parameters for the container "
|
||||
mkdir -p /etc/systemd/nspawn
|
||||
|
||||
cat <<EOF > /etc/systemd/nspawn/"$container_name".nspawn
|
||||
[Exec]
|
||||
Boot=on
|
||||
|
||||
[Network]
|
||||
MACVLAN=br$vlan_id
|
||||
ResolvConf=off
|
||||
EOF
|
||||
|
||||
##### Configure the Container to use an Isolated MacVLAN Network
|
||||
echo " Configuring the Container to use an Isolated MacVLAN Network"
|
||||
cd /data/on_boot.d
|
||||
if [ -f "$file" ] ; then
|
||||
rm "$file"
|
||||
fi
|
||||
curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/nspawn/nspawn-container/scripts/10-setup-network.sh
|
||||
chmod +x 10-setup-network.sh
|
||||
|
||||
cat <<EOF > /etc/systemd/nspawn/"$container_name".nspawn
|
||||
[Exec]
|
||||
Boot=on
|
||||
|
||||
[Network]
|
||||
MACVLAN=br$vlan_id
|
||||
ResolvConf=off
|
||||
EOF
|
||||
|
||||
#####Configure your container to set the IP and gateway you defined in 10-setup-network.sh
|
||||
cd /data/custom/machines/"$container_name"/etc/systemd/network
|
||||
|
||||
cat <<EOF > mv-br${vlan_id}.network
|
||||
[Match]
|
||||
Name=mv-br$vlan_id
|
||||
|
||||
[Network]
|
||||
IPForward=yes
|
||||
Address=$vlan_address
|
||||
Gateway=$vlan_gateway
|
||||
EOF
|
||||
|
||||
#### Run the 10-setup-network.sh script to setup the network interface
|
||||
/data/on_boot.d/10-setup-network.sh
|
||||
machinectl stop "$container_name"
|
||||
machinectl start "$container_name"
|
||||
|
||||
}
|
||||
|
||||
function setup_adguard() {
|
||||
echo "You have selected to setup a AdGuardHome in container $container_name"
|
||||
read -p "Press enter to continue OR ctrl + c to cancel."
|
||||
|
||||
echo ""
|
||||
echo " Setting up adguard"
|
||||
echo ""
|
||||
############ install addguard #######
|
||||
|
||||
systemd-nspawn -M "$container_name" -D /data/custom/machines/"$container_name" /bin/bash -c "apt -y install curl &&
|
||||
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v"
|
||||
|
||||
|
||||
echo "Go to http://${vlan_address}:3000 to configure AdGuard Home (or whatever IP your container has if you had select simple install)."
|
||||
read -p "Press enter to continue"
|
||||
|
||||
}
|
||||
|
||||
function setup_persistence() {
|
||||
echo ""
|
||||
echo " Configuring Persistence Across Firmware Updates"
|
||||
echo ""
|
||||
#### Configure Persistence Across Firmware Updates
|
||||
echo "Configuring Persistence Across Firmware Updates"
|
||||
cd /data/on_boot.d
|
||||
curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/nspawn/nspawn-container/scripts/0-setup-system.sh
|
||||
chmod +x 0-setup-system.sh
|
||||
|
||||
mv 0-setup-system.sh 02-setup-system.sh
|
||||
}
|
||||
|
||||
function setup_backup_dpkg_files() {
|
||||
echo ""
|
||||
echo " Downloading the backup dpkg package files"
|
||||
echo ""
|
||||
#### Download the backup dpkg package files for systemd-container and dependencies into /data/custom/dpkg.
|
||||
#####These packages will only be used as a backup install in case the Internet is down after the first boot after an update.
|
||||
echo "Configuring backup install"
|
||||
mkdir -p /data/custom/dpkg && cd /data/custom/dpkg
|
||||
apt download systemd-container libnss-mymachines debootstrap arch-test
|
||||
|
||||
echo " Container setup has ended .. :) "
|
||||
}
|
||||
|
||||
menu(){
|
||||
echo -ne "
|
||||
Create a container with systemd-nspawn
|
||||
Select your option from below:
|
||||
$(ColorGreen '1)') Create a Custom Container Simple
|
||||
$(ColorGreen '2)') Create a Custom Container Mac Vlan
|
||||
$(ColorGreen '3)') Install Adguard in existing container.
|
||||
$(ColorGreen '4)') Print set Variables.
|
||||
$(ColorGreen '5)') Set Container Variables (name & Root Password).
|
||||
$(ColorGreen '6)') Set Container Network Variables. (Vlan ID & IP address).
|
||||
$(ColorGreen '0)') Exit
|
||||
$(ColorBlue 'Choose an option:') "
|
||||
read a
|
||||
case $a in
|
||||
1) create_custom_container_simple ; menu ;;
|
||||
2) create_custom_container_macvlan ; menu ;;
|
||||
3) setup_adguard ; menu ;;
|
||||
4) echo_variables ; menu ;;
|
||||
5) set_variables ; menu ;;
|
||||
6) set_container_network_variables ; menu ;;
|
||||
0) exit 0 ;;
|
||||
*) echo -e $red"Wrong option."$clear; WrongCommand;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Call the menu function
|
||||
menu
|
20
nspawn-container/scripts/0-setup-system.sh
Normal file
20
nspawn-container/scripts/0-setup-system.sh
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# This script installs systemd-container if it's not installed.
|
||||
# Also links any containers from /data/custom/machines to /var/lib/machines.
|
||||
|
||||
set -e
|
||||
|
||||
if ! dpkg -l systemd-container | grep ii >/dev/null; then
|
||||
if ! apt -y install systemd-container debootstrap; then
|
||||
yes | dpkg -i /data/custom/dpkg/*.deb
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p /var/lib/machines
|
||||
for machine in $(ls /data/custom/machines/); do
|
||||
if [ ! -e "/var/lib/machines/$machine" ]; then
|
||||
ln -s "/data/custom/machines/$machine" "/var/lib/machines/"
|
||||
machinectl enable $machine
|
||||
machinectl start $machine
|
||||
fi
|
||||
done
|
84
nspawn-container/scripts/10-setup-network.sh
Normal file
84
nspawn-container/scripts/10-setup-network.sh
Normal file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# This script will create a macvlan bridge interface to allow communication
|
||||
# between container networks and host networks.
|
||||
# An interface called brX.mac will be created, where X = $VLAN configured below.
|
||||
# The interface will be assigned an IP of $IPV4_GW, and $IPV6_GW configured below.
|
||||
# Routes will be added for the container IP $IPV4 and $IPV6.
|
||||
# Script is based on 10-dns.sh from unifios-utilities.
|
||||
|
||||
## CONFIGURATION VARIABLES
|
||||
|
||||
# VLAN ID network container will be on. This VLAN has to first be configured as a
|
||||
# network in Unifi Network settings with a unique IP/subnet. Do not use the same
|
||||
# IP in the unifi network settings as you will use below for IPV4_IP or IPV4_GW.
|
||||
VLAN=5
|
||||
|
||||
# IP addresses of container.
|
||||
IPV4_IP="10.0.5.3"
|
||||
# Gateway IP address of macvlan interface. IP above should be in this subnet.
|
||||
IPV4_GW="10.0.5.1/24"
|
||||
|
||||
# IPv6 container and gateway addresses. These can be empty if not using IPv6.
|
||||
# Preferably generate your own ULA instead of using the default one below.
|
||||
# A public IPv6 prefix based on your ISP's prefix can be used too, but any
|
||||
# prefix changes for dynamic IPv6 prefixes have to be modified manually.
|
||||
IPV6_IP="fd62:89a2:fda9:e23::3"
|
||||
IPV6_GW="fd62:89a2:fda9:e23::1/64"
|
||||
|
||||
# Set this to the interface(s) on which you want DNS TCP/UDP port 53 traffic
|
||||
# re-routed through this container. Separate interfaces with spaces.
|
||||
# This is useful when runinng a DNS service, like Adguard Home
|
||||
# e.g. "br0" or "br0 br1" etc.
|
||||
FORCED_INTFC=""
|
||||
|
||||
## END OF CONFIGURATION
|
||||
|
||||
# set VLAN bridge promiscuous
|
||||
ip link set "br${VLAN}" promisc on
|
||||
|
||||
# create macvlan bridge and add IPv4 IP
|
||||
ip link add "br${VLAN}.mac" link "br${VLAN}" type macvlan mode bridge
|
||||
ip addr add "${IPV4_GW}" dev "br${VLAN}.mac" noprefixroute
|
||||
|
||||
# (optional) add IPv6 IP to VLAN bridge macvlan bridge
|
||||
if [ -n "${IPV6_GW}" ]; then
|
||||
ip -6 addr add "${IPV6_GW}" dev "br${VLAN}.mac" noprefixroute
|
||||
fi
|
||||
|
||||
# set macvlan bridge promiscuous and bring it up
|
||||
ip link set "br${VLAN}.mac" promisc on
|
||||
ip link set "br${VLAN}.mac" up
|
||||
|
||||
# add IPv4 route to container
|
||||
ip route add "${IPV4_IP}/32" dev "br${VLAN}.mac"
|
||||
|
||||
# (optional) add IPv6 route to container
|
||||
if [ -n "${IPV6_IP}" ]; then
|
||||
ip -6 route add "${IPV6_IP}/128" dev "br${VLAN}.mac"
|
||||
fi
|
||||
|
||||
# Make DNSMasq listen to the container network for split horizon or conditional forwarding
|
||||
if ! grep -qxF "interface=br${VLAN}.mac" /run/dnsmasq.conf.d/custom.conf; then
|
||||
echo "interface=br${VLAN}.mac" >>/run/dnsmasq.conf.d/custom.conf
|
||||
kill -9 "$(cat /run/dnsmasq.pid)"
|
||||
fi
|
||||
|
||||
# (optional) IPv4 force DNS (TCP/UDP 53) through DNS container
|
||||
for intfc in ${FORCED_INTFC}; do
|
||||
if [ -d "/sys/class/net/${intfc}" ]; then
|
||||
for proto in udp tcp; do
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV4_IP} ! -d ${IPV4_IP} --dport 53 -j LOG --log-prefix [DNAT-${intfc}-${proto}]"
|
||||
iptables -t nat -C ${prerouting_rule} 2>/dev/null || iptables -t nat -A ${prerouting_rule}
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV4_IP} ! -d ${IPV4_IP} --dport 53 -j DNAT --to ${IPV4_IP}"
|
||||
iptables -t nat -C ${prerouting_rule} 2>/dev/null || iptables -t nat -A ${prerouting_rule}
|
||||
|
||||
# (optional) IPv6 force DNS (TCP/UDP 53) through DNS container
|
||||
if [ -n "${IPV6_IP}" ]; then
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV6_IP} ! -d ${IPV6_IP} --dport 53 -j LOG --log-prefix [DNAT-${intfc}-${proto}]"
|
||||
ip6tables -t nat -C ${prerouting_rule} 2>/dev/null || ip6tables -t nat -A ${prerouting_rule}
|
||||
prerouting_rule="PREROUTING -i ${intfc} -p ${proto} ! -s ${IPV6_IP} ! -d ${IPV6_IP} --dport 53 -j DNAT --to ${IPV6_IP}"
|
||||
ip6tables -t nat -C ${prerouting_rule} 2>/dev/null || ip6tables -t nat -A ${prerouting_rule}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
13
nspawn-container/scripts/setup-network.service
Normal file
13
nspawn-container/scripts/setup-network.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Setup custom container network service
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/data/on_boot.d/10-setup-network.sh
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
15
nspawn-container/scripts/setup-system.service
Normal file
15
nspawn-container/scripts/setup-system.service
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Setup custom container service
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/data/on_boot.d/0-setup-system.sh
|
||||
RemainAfterExit=yes
|
||||
RestartSec=30
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
18
on-boot-script-2.x/Dockerfile
Normal file
18
on-boot-script-2.x/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
RUN set -ex \
|
||||
&& echo 'deb http://deb.debian.org/debian bookworm-backports main' > /etc/apt/sources.list.d/backports.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
devscripts \
|
||||
fakeroot \
|
||||
debhelper=12.\* dh-autoreconf=17\* \
|
||||
&& apt-get -y autoremove \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /tmp/* /var/tmp/* /var/log/* /var/lib/apt/lists/* /var/log/alternatives.log
|
||||
|
||||
RUN chmod a+rwx,u+t /tmp
|
||||
|
||||
ENTRYPOINT []
|
||||
CMD ["/bin/sh"]
|
61
on-boot-script-2.x/README.md
Normal file
61
on-boot-script-2.x/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# UDM / UDMPro Boot Script
|
||||
|
||||
## Features
|
||||
|
||||
1. Allows you to run a shell script at S95 anytime your UDM starts / reboots
|
||||
|
||||
## Compatibility
|
||||
|
||||
1. Should work on any UDM/UDMPro after 2.4.x
|
||||
|
||||
- [build_deb.sh](build_deb.sh) can be used to build the package by yourself.
|
||||
|
||||
- [dpkg-build-files](dpkg-build-files) contains the sources that debuild uses to build the package if you want to build it yourself / change it
|
||||
- by default it uses docker or podman to build the debian package
|
||||
- use `./build_deb.sh build` to not use a container
|
||||
- the resulting package will be in [packages/](packages/)
|
||||
|
||||
- Built on Ubuntu-20.04 on Windows 10/WSL2
|
||||
|
||||
## Install
|
||||
|
||||
You can execute in UDM/Pro/SE and UDR with:
|
||||
|
||||
```bash
|
||||
curl -fsL "https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/on-boot-script-2.x/remote_install.sh" | /bin/bash
|
||||
```
|
||||
|
||||
This is a force to install script so will uninstall any previous version and install on_boot keeping your on boot files.
|
||||
|
||||
This will also install CNI Plugins & CNI Bridge scripts. If you are using UDMSE/UDR remember that you must install podman manually because there is no podman.
|
||||
|
||||
## Manually Install Steps
|
||||
|
||||
1. Get into the unifios shell on your udm
|
||||
|
||||
```bash
|
||||
unifi-os shell
|
||||
```
|
||||
|
||||
2. Download [udm-boot-2x_1.0.1_all.deb](packages/udm-boot-2x_1.0.1_all.deb) and install it and go back to the UDM.
|
||||
|
||||
```bash
|
||||
curl -L [[https://unifi.boostchicken.io/udm-boot-v2+/udm-boot-2x_1.0.1_all.deb](https://unifi.boostchicken.io/udm-boot-v2+/udm-boot-2x_1.0.1_all.deb)](https://unifi.boostchicken.io/udm-boot-v2+/udm-boot-2x_1.0.1_all.deb) -o udm-boot-2x_1.0.1_all.deb
|
||||
dpkg -i udm-boot-2x_1.0.1_all.deb
|
||||
systemctl enable udm-boot
|
||||
exit
|
||||
```
|
||||
|
||||
3. Copy any shell scripts you want to run to /data/on_boot.d on your UDM (not the unifi-os shell) and make sure they are executable and have the correct shebang (#!/bin/bash). Additionally, scripts need to have a `.sh` extention in their filename.
|
||||
|
||||
Examples:
|
||||
|
||||
- Start a DNS Container [10-dns.sh](../dns-common/on_boot.d/10-dns.sh)
|
||||
- Start wpa_supplicant [on_boot.d/10-wpa_supplicant.sh](examples/udm-files/on_boot.d/10-wpa_supplicant.sh)
|
||||
- Add a persistent ssh key for the root user [on_boot.d/15-add-root-ssh-keys.sh](examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh)
|
||||
|
||||
## Version History
|
||||
|
||||
### 1.0.0
|
||||
|
||||
- First release that persists through firmware
|
101
on-boot-script-2.x/build_deb.sh
Executable file
101
on-boot-script-2.x/build_deb.sh
Executable file
@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
WORK_DIR="$(cd "$(dirname "$0")" && echo "${PWD}")"
|
||||
TARGET_DIR="${WORK_DIR}/packages"
|
||||
SOURCE_DIR="${WORK_DIR}/dpkg-build-files"
|
||||
CONTAINER_FILE="${WORK_DIR}/Dockerfile"
|
||||
CONTAINER_CONTEXT="${WORK_DIR}"
|
||||
|
||||
fatal() {
|
||||
echo "ERROR: ${1}" 1>&2
|
||||
exit ${2-1}
|
||||
}
|
||||
|
||||
build_in_container=false
|
||||
build=false
|
||||
build_container=false
|
||||
if [ $# -eq 0 ]; then
|
||||
build_in_container=true
|
||||
fi
|
||||
if [ "${1}" = "build" ]; then
|
||||
build=true
|
||||
fi
|
||||
if [ "${1}" = "build_container" ]; then
|
||||
build_container=true
|
||||
fi
|
||||
|
||||
|
||||
build_in_container() {
|
||||
docker_exec="$(command -v docker || true)"
|
||||
podman_exec="$(command -v podman || true)"
|
||||
container_exec="${docker_exec:-"${podman_exec}"}"
|
||||
container_args=""
|
||||
|
||||
if [ ! -f "${container_exec}" ]; then
|
||||
fatal "docker or podman not found"
|
||||
fi
|
||||
if [ ! -f "${CONTAINER_FILE}" ]; then
|
||||
fatal "container file ${CONTAINER_FILE} not found"
|
||||
fi
|
||||
|
||||
if [ "${container_exec}" = "${docker_exec}" ]; then
|
||||
# docker does not map user, so we run it as user
|
||||
container_args="--user "$(id -u):$(id -g)""
|
||||
fi
|
||||
"${container_exec}" build --file "${CONTAINER_FILE}" --tag udm-boot-deb-builder "${CONTAINER_CONTEXT}"
|
||||
"${container_exec}" run -it \
|
||||
${container_args} \
|
||||
-v "${SOURCE_DIR}:/source:ro" \
|
||||
-v "${TARGET_DIR}:/target:rw" \
|
||||
-v "${WORK_DIR}/build_deb.sh:/build_deb.sh:ro" \
|
||||
--rm \
|
||||
udm-boot-deb-builder \
|
||||
/build_deb.sh build_container
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
source_dir=$1
|
||||
target_dir=$2
|
||||
version="$(dpkg-parsechangelog --show-field version -l "${source_dir}/debian/changelog")"
|
||||
name="$(dpkg-parsechangelog --show-field source -l "${source_dir}/debian/changelog")"
|
||||
package_name="${name}-${version}"
|
||||
build_dir="$(mktemp --tmpdir="/tmp" --directory "${name}.XXXXXXXXXX")"
|
||||
build_package_dir="${build_dir}/${package_name}"
|
||||
|
||||
if [ ! -d "${source_dir}" ]; then
|
||||
fatal "source dir ${source_dir} not found"
|
||||
fi
|
||||
if [ ! -d "${target_dir}" ]; then
|
||||
fatal "target dir ${target_dir} not found"
|
||||
fi
|
||||
|
||||
mkdir -p "${build_package_dir}"
|
||||
cp -r "${source_dir}"/* "${build_package_dir}"
|
||||
(
|
||||
cd "${build_package_dir}"
|
||||
# we could exclude "source" here to skip building the source,
|
||||
# but lintian warns only in the source build about some stuff
|
||||
debuild -us -uc --build=source,all --lintian-opts --profile debian
|
||||
)
|
||||
|
||||
find "${build_dir}" -maxdepth 1 -type f -exec mv {} "${target_dir}" \;
|
||||
rm -rf "${build_dir}"
|
||||
}
|
||||
|
||||
build_container() {
|
||||
build "/source" "/target"
|
||||
}
|
||||
|
||||
if [ $build_in_container = true ]; then
|
||||
build_in_container
|
||||
fi
|
||||
if [ $build = true ]; then
|
||||
build "${SOURCE_DIR}" "${TARGET_DIR}"
|
||||
fi
|
||||
if [ $build_container = true ]; then
|
||||
build_container
|
||||
fi
|
||||
|
12
on-boot-script-2.x/dpkg-build-files/debian/changelog
Normal file
12
on-boot-script-2.x/dpkg-build-files/debian/changelog
Normal file
@ -0,0 +1,12 @@
|
||||
udm-boot-2x (1.0.1) stable; urgency=medium
|
||||
|
||||
* Using bash to invoke
|
||||
|
||||
-- Boostchicken <john@boostchicken.dev> Sat, 21 Feb 2023 18:46:14 -0700
|
||||
|
||||
|
||||
udm-boot-2x (1.0.0) stable; urgency=medium
|
||||
|
||||
* Initial release, happy firmware persisting!
|
||||
|
||||
-- Boostchicken <john@boostchicken.dev> Sat, 18 Feb 2023 18:46:14 -0700
|
15
on-boot-script-2.x/dpkg-build-files/debian/control
Normal file
15
on-boot-script-2.x/dpkg-build-files/debian/control
Normal file
@ -0,0 +1,15 @@
|
||||
Source: udm-boot-2x
|
||||
Section: contrib/utils
|
||||
Priority: optional
|
||||
Maintainer: Boostchicken <john@boostchicken.dev>
|
||||
Build-Depends: debhelper-compat (= 12)
|
||||
Standards-Version: 4.4.1
|
||||
Homepage: https://github.com/unifi-utilities/unifios-utilities
|
||||
#Vcs-Browser: https://salsa.debian.org/debian/udmboot
|
||||
#Vcs-Git: https://salsa.debian.org/debian/udmboot.git
|
||||
|
||||
Package: udm-boot-2x
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}
|
||||
Description: Run things on boot on UDM 2.x
|
||||
Run things on boot!
|
9
on-boot-script-2.x/dpkg-build-files/debian/copyright
Normal file
9
on-boot-script-2.x/dpkg-build-files/debian/copyright
Normal file
@ -0,0 +1,9 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: udm-boot-2x
|
||||
Upstream-Contact: John Dorman / Boostchicken
|
||||
Source: https://github.com/unifi-utilities/unifi-utilities
|
||||
|
||||
Files: *
|
||||
Copyright: 2023 john@boostchicken.dev
|
||||
License: GPL-3
|
||||
https://github.com/unifi-utilities/unifi-utilities/blob/main/LICENSE
|
1
on-boot-script-2.x/dpkg-build-files/debian/install
Normal file
1
on-boot-script-2.x/dpkg-build-files/debian/install
Normal file
@ -0,0 +1 @@
|
||||
udm-boot.service lib/systemd/system/
|
40
on-boot-script-2.x/dpkg-build-files/debian/postinst
Normal file
40
on-boot-script-2.x/dpkg-build-files/debian/postinst
Normal file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# postinst script for udm-boot
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
alias deb-systemd-invoke='systemctl --no-block --'
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
on-boot-script-2.x/dpkg-build-files/debian/postrm
Executable file
38
on-boot-script-2.x/dpkg-build-files/debian/postrm
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# postrm script for udm-boot
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
true
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
37
on-boot-script-2.x/dpkg-build-files/debian/preinst
Executable file
37
on-boot-script-2.x/dpkg-build-files/debian/preinst
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
# preinst script for udm-boot
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
|
||||
true
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
40
on-boot-script-2.x/dpkg-build-files/debian/prerm
Executable file
40
on-boot-script-2.x/dpkg-build-files/debian/prerm
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# prerm script for udm-boot
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
# reserved for future use
|
||||
true
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
8
on-boot-script-2.x/dpkg-build-files/debian/rules
Executable file
8
on-boot-script-2.x/dpkg-build-files/debian/rules
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_builddeb:
|
||||
dh_builddeb -- -Zgzip
|
||||
|
1
on-boot-script-2.x/dpkg-build-files/debian/source/format
Normal file
1
on-boot-script-2.x/dpkg-build-files/debian/source/format
Normal file
@ -0,0 +1 @@
|
||||
3.0 (native)
|
@ -0,0 +1,3 @@
|
||||
udm-boot-2x source: changelog-should-mention-nmu
|
||||
udm-boot-2x source: source-nmu-has-incorrect-version-number
|
||||
udm-boot-2x source: odd-historical-debian-changelog-version
|
16
on-boot-script-2.x/dpkg-build-files/udm-boot.service
Normal file
16
on-boot-script-2.x/dpkg-build-files/udm-boot.service
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Run On Startup UDM 2.x
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
StartLimitIntervalSec=500
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=bash -c 'mkdir -p /data/on_boot.d && find -L /data/on_boot.d -mindepth 1 -maxdepth 1 -type f -print0 | sort -z | xargs -0 -r -n 1 -- sh -c '\''if test -x "$0"; then echo "%n: running $0"; "$0"; else case "$0" in *.sh) echo "%n: sourcing $0"; . "$0";; *) echo "%n: ignoring $0";; esac; fi'\'
|
||||
RemainAfterExit=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## Configure shell profile
|
||||
|
||||
device_info() {
|
||||
echo $(/usr/bin/ubnt-device-info "$1")
|
||||
}
|
||||
|
||||
# Modify login banner (motd)
|
||||
cat >/etc/motd <<EOF
|
||||
Welcome to UniFi Dream Machine!
|
||||
(c) 2010-$(date +%Y) Ubiquiti Inc. | http://www.ui.com
|
||||
|
||||
Model: $(device_info model)
|
||||
Version: $(device_info firmware)
|
||||
MAC Address: $(device_info mac)
|
||||
EOF
|
||||
|
||||
# Extend UbiOS prompt to include useful information
|
||||
cat >/etc/profile.d/prompt.sh <<'EOF'
|
||||
UDM_NAME="$(grep -m 1 '^name:' ${DATA_DIR}/unifi-core/config/settings.yaml | awk -F: '{ gsub(/^[ \t]+|[ \t]+$/, "", $2); print tolower($2) }')"
|
||||
PROMPT_MAIN="\u@${UDM_NAME}:\w"
|
||||
|
||||
export PS1="[UDM] ${PROMPT_MAIN}${PS1}"
|
||||
EOF
|
||||
|
||||
# Copy all global profile scripts (for all users) from `${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/` directory
|
||||
mkdir -p ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d
|
||||
cp -rf ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/* /etc/profile.d/
|
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
## create files like this with different numbers for execution order
|
||||
## ala /etc/profile.d
|
||||
|
||||
## example command to run, please replace with your own.
|
||||
podman start wpa_supplicant-udmpro
|
19
on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh
Executable file
19
on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
3*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
cp -f ${DATA_DIR}/on_boot.d/files/.profile /root/
|
@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## Config Variables - please edit these
|
||||
# Set to true to download public keys from a github user account
|
||||
USE_GITHUB_KEYS=true
|
||||
# Enter your username on github to get the public keys for
|
||||
GITHUB_USER="<YOUR_USERNAME>"
|
||||
# File location for the output of the git download
|
||||
GITHUB_KEY_PATH="${DATA_DIR}/podman/ssh"
|
||||
GITHUB_KEY_FILE="${GITHUB_KEY_PATH}/github.keys"
|
||||
# Set to true to use a file containing a key per line in the format ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAA...\n
|
||||
USE_KEY_FILE=true
|
||||
# IF using an input file, list it here
|
||||
INPUT_KEY_PATH="${DATA_DIR}/podman/ssh"
|
||||
INPUT_KEY_FILE="${INPUT_KEY_PATH}/ssh.keys"
|
||||
# The target key file for the script
|
||||
OUTPUT_KEY_PATH="/root/.ssh"
|
||||
OUTPUT_KEY_FILE="${OUTPUT_KEY_PATH}/authorized_keys"
|
||||
|
||||
## Functions
|
||||
# This function downloads the keys from the selected github user
|
||||
download_from_github() {
|
||||
if curl --output /dev/null --silent --head --fail https://github.com/${GITHUB_USER}.keys; then
|
||||
curl https://github.com/${GITHUB_USER}.keys -o ${GITHUB_KEY_FILE}
|
||||
echo "Downloaded keys from Github"
|
||||
else
|
||||
echo "Could not download ${GITHUB_USER}'s key file from github"
|
||||
fi
|
||||
}
|
||||
# Write line to the output line. Add the input line as an arguement.
|
||||
write_to_output() {
|
||||
# Check the file exits
|
||||
if ! test -f ${OUTPUT_KEY_FILE}; then
|
||||
echo "File at ${OUTPUT_KEY_FILE} does not exist, creating it"
|
||||
touch ${OUTPUT_KEY_FILE}
|
||||
fi
|
||||
echo "${1}" >>${OUTPUT_KEY_FILE}
|
||||
}
|
||||
# This function reads keys from a file into the requested file. The arguement is the input file.
|
||||
use_key_from_file() {
|
||||
if ! test -f $1; then
|
||||
echo "File $1 does not exist"
|
||||
return
|
||||
fi
|
||||
counter=0
|
||||
while IFS= read -r line; do
|
||||
write_to_output "${line}"
|
||||
let "counter++"
|
||||
done <$1
|
||||
echo "${counter} number of entries read from "
|
||||
}
|
||||
|
||||
## Script
|
||||
# Makes paths if they don't exit
|
||||
mkdir -p ${GITHUB_KEY_PATH} ${INPUT_KEY_PATH} ${OUTPUT_KEY_PATH}
|
||||
#Check flags to see which files to use
|
||||
if [ ${USE_GITHUB_KEYS} = true ]; then
|
||||
download_from_github
|
||||
use_key_from_file ${GITHUB_KEY_FILE}
|
||||
fi
|
||||
if [ ${USE_KEY_FILE} = true ]; then
|
||||
use_key_from_file ${INPUT_KEY_FILE}
|
||||
fi
|
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## Places public keys in ~/.ssh/authorized_keys
|
||||
|
||||
KEYS_SOURCE_FILE="${DATA_DIR}/on_boot.d/settings/ssh/authorized_keys"
|
||||
KEYS_TARGET_FILE="/root/.ssh/authorized_keys"
|
||||
|
||||
count_added=0
|
||||
count_skipped=0
|
||||
while read -r key; do
|
||||
# Places public key in ~/.ssh/authorized_keys if not present
|
||||
if ! grep -Fxq "$key" "$KEYS_TARGET_FILE"; then
|
||||
let count_added++
|
||||
echo "$key" >>"$KEYS_TARGET_FILE"
|
||||
else
|
||||
let count_skipped++
|
||||
fi
|
||||
done <"$KEYS_SOURCE_FILE"
|
||||
|
||||
echo "${count_added} keys added to ${KEYS_TARGET_FILE}"
|
||||
if [ $count_skipped -gt 0 ]; then
|
||||
echo "${count_skipped} already added keys skipped"
|
||||
fi
|
||||
|
||||
# Convert ssh key to dropbear for shell interaction
|
||||
echo "Converting SSH private key to dropbear format"
|
||||
dropbearconvert openssh dropbear ${DATA_DIR}/ssh/id_rsa /root/.ssh/id_dropbear
|
||||
|
||||
exit 0
|
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
#####################################################
|
||||
# ADD KNOWN HOSTS AS BELOW - CHANGE BEFORE RUNNING #
|
||||
#####################################################
|
||||
# set -- "known host text on a line with quotes " \ #
|
||||
# "second known host on another line " \ #
|
||||
# "one per line, last line has no backslash" #
|
||||
#####################################################
|
||||
set -- "hostname ecdsa-sha2-nistp256 AAAABIGHOSTIDENTIFIERWITHMAGICSTUFF=" \
|
||||
"otherhost ecdsa-sha2-nistp256 AAAADIFFERENTHOSTMAGICSTUFF!@HJKSL="
|
||||
|
||||
KNOWN_HOSTS_FILE="/root/.ssh/known_hosts"
|
||||
|
||||
counter=0
|
||||
for host in "$@"; do
|
||||
## Places known host in ~/.ssh/known_hosts if not present
|
||||
if ! grep -Fxq "$host" "$KNOWN_HOSTS_FILE"; then
|
||||
let counter++
|
||||
echo "$host" >>"$KNOWN_HOSTS_FILE"
|
||||
fi
|
||||
done
|
||||
|
||||
echo $counter hosts added to $KNOWN_HOSTS_FILE
|
||||
|
||||
exit 0
|
26
on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh
Executable file
26
on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
mkdir -p ${DATA_DIR}/.home
|
||||
|
||||
for file in .ash_history .bash_history; do
|
||||
if [ ! -f ${DATA_DIR}/.home/$file ]; then
|
||||
touch /root/$file
|
||||
cp /root/$file ${DATA_DIR}/.home/$file
|
||||
chown root:root ${DATA_DIR}/.home/$file
|
||||
chmod 0600 ${DATA_DIR}/.home/$file
|
||||
fi
|
||||
ln -sf ${DATA_DIR}/.home/$file /root/$file
|
||||
done
|
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
## create files like this with different numbers for execution order
|
||||
## ala /etc/profile.d
|
||||
|
||||
## Start the ntopng-udm container, from https://github.com/tusc/ntopng-udm
|
||||
podman start ntopng
|
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2* | 3* | 4*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## Store crontab files in ${DATA_DIR}/cronjobs/ (you will need to create this folder).
|
||||
## This script will re-add them on startup.
|
||||
|
||||
cp ${DATA_DIR}/cronjobs/* /etc/cron.d/
|
||||
/etc/init.d/crond restart
|
||||
|
||||
exit 0
|
10
on-boot-script-2.x/examples/udm-files/on_boot.d/50-start-node-exporter.sh
Executable file
10
on-boot-script-2.x/examples/udm-files/on_boot.d/50-start-node-exporter.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONTAINER=node-exporter
|
||||
|
||||
# Starts a Prometheus node-exporter container that is deleted after it is stopped.
|
||||
if podman container exists "${CONTAINER}"; then
|
||||
podman start "${CONTAINER}"
|
||||
else
|
||||
podman run -d --rm --name "${CONTAINER}" --net="host" --pid="host" -v "/:/host:ro,rslave" quay.io/prometheus/node-exporter:latest --path.rootfs=/host
|
||||
fi
|
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
alias -='cd -'
|
||||
alias ...=../..
|
||||
alias ....=../../..
|
||||
alias .....=../../../..
|
||||
alias ......=../../../../..
|
||||
alias cp='cp -i'
|
||||
alias la='ls -lAFh'
|
||||
alias ll='ls -l'
|
||||
alias md='mkdir -p'
|
||||
alias mkcd='foo(){ mkdir -p "$1"; cd "$1" }; foo'
|
||||
alias mv='mv -i'
|
||||
alias rd=rmdir
|
||||
alias rm='rm -i'
|
@ -0,0 +1,100 @@
|
||||
#!/bin/bash
|
||||
# Get DataDir location
|
||||
DATA_DIR="/data"
|
||||
case "$(ubnt-device-info firmware || true)" in
|
||||
1*)
|
||||
DATA_DIR="/mnt/data"
|
||||
;;
|
||||
2*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
3*)
|
||||
DATA_DIR="/data"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: No persistent storage found." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
## ----------------------------------------------------------------------
|
||||
## Script to add/remove time-of-day restrictions on internet access for selected clients.
|
||||
##
|
||||
## Use DHCP reservations to encourage the selected clients to always obtain the same IP address.
|
||||
##
|
||||
## To install:
|
||||
## * Copy this script into ${DATA_DIR}/on_boot.d/, using something like WinSCP or SSH + vi.
|
||||
## * Grant Execute permission: chmod +x ${DATA_DIR}/on_boot.d/iptables_timerestrict.sh
|
||||
## * Run it once, to activate it (crontab entries will keep it active forever after):
|
||||
## Via SSH into UDM shell: ${DATA_DIR}/on_boot.d/iptables_timerestrict.sh
|
||||
##
|
||||
## Notes:
|
||||
## * Changes to firewall rules in the Unifi Network Application will remove your restriction;
|
||||
## re-run this script to re-apply the restriction rule, or wait for the next activation/deactivation hour.
|
||||
## * To apply changes to this script (i.e. new client addresses, or changes to the time of day),
|
||||
## re-run this script manually to apply the updates, or wait for the next activation/deactivation hour.
|
||||
## * When this script activates or deactivates the blocking, it will log to /var/log/messages.
|
||||
## * While the blocking is active, you'll see one "TIMERESTRICT BLOCK: " log message per hour
|
||||
## in /var/log/messages if any blocked clients are attempting to use the internet.
|
||||
##
|
||||
## Caveats:
|
||||
## * No support for wake_minute/sleep_minute - currently this only turns on/off at the top of an hour.
|
||||
## * Assumption exists that sleep_hour is always greater-than wake_hour; i.e., you can't currently
|
||||
## have a blocked time in the middle of the day.
|
||||
## ----------------------------------------------------------------------
|
||||
|
||||
## List all client addresses you'd like to restrict. Separate multiple with spaces.
|
||||
timerestricted_addresses='192.168.1.101 192.168.1.102'
|
||||
|
||||
## Hour of day to remove the restriction.
|
||||
wake_hour=06
|
||||
|
||||
## Hour of day to activate the restriction.
|
||||
sleep_hour=23
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## ----------------------------------------------------------------------
|
||||
## ----------------------------------------------------------------------
|
||||
|
||||
myrule="FORWARD -i br0 -j TIMERESTRICT"
|
||||
|
||||
## report on blocks if rule exists
|
||||
iptables -C $myrule 2>/dev/null && iptables -vL TIMERESTRICT | logger
|
||||
|
||||
echo "Setting up timerestrict firewall rules between $sleep_hour:00 and $wake_hour:00"
|
||||
|
||||
## initial setup
|
||||
iptables -N TIMERESTRICT_LOGNDROP 2>/dev/null
|
||||
iptables -F TIMERESTRICT_LOGNDROP 2>/dev/null
|
||||
iptables -A TIMERESTRICT_LOGNDROP -m limit --limit 1/hour --limit-burst 1 -j LOG --log-prefix "TIMERESTRICT BLOCK: "
|
||||
iptables -A TIMERESTRICT_LOGNDROP -j REJECT --reject-with icmp-net-prohibited
|
||||
|
||||
iptables -N TIMERESTRICT 2>/dev/null
|
||||
iptables -F TIMERESTRICT 2>/dev/null
|
||||
for ip in $timerestricted_addresses; do
|
||||
iptables -A TIMERESTRICT -s $ip -j TIMERESTRICT_LOGNDROP
|
||||
done
|
||||
|
||||
myrule="FORWARD -i br0 -j TIMERESTRICT"
|
||||
|
||||
## install or remove rule based on current time and whether the rule already exists
|
||||
if [ $(date +%H) -ge $sleep_hour ]; then
|
||||
logger "TIMERESTRICT: Activating sleep time"
|
||||
iptables -C $myrule 2>/dev/null || iptables -I $myrule
|
||||
elif [ $(date +%H) -ge $wake_hour ]; then
|
||||
logger "TIMERESTRICT: Activating awake time"
|
||||
iptables -C $myrule 2>/dev/null && iptables -D $myrule
|
||||
fi
|
||||
|
||||
## setup cron job to activate/deactivate on time of day
|
||||
echo "00 $sleep_hour * * * $(readlink -f $0)" >/etc/cron.d/iptables_timerestrict
|
||||
echo "00 $wake_hour * * * $(readlink -f $0)" >>/etc/cron.d/iptables_timerestrict
|
||||
## Format: <minute> <hour> <day> <month> <dow> <tags and command>
|
||||
/etc/init.d/crond restart
|
||||
|
||||
echo "Done with firewall rule setup:"
|
||||
echo "-------------------------------------------------------------------"
|
||||
iptables -vL FORWARD | egrep '(Chain|pkts|TIMERESTRICT)'
|
||||
echo ...
|
||||
iptables -vL TIMERESTRICT
|
||||
iptables -vL TIMERESTRICT_LOGNDROP
|
||||
echo
|
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
## Create network bridge for CNI
|
||||
|
||||
ip link show cni0 > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ip link add cni0 type bridge
|
||||
fi
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user