Initial commit

This commit is contained in:
2024-10-30 01:50:38 +01:00
commit 587ca23374
147 changed files with 7521 additions and 0 deletions

108
roles/dhcp/README.md Normal file
View File

@@ -0,0 +1,108 @@
# `flyoverhead.openwrt.dhcp`
OpenWRT `dhcp` configuration
- configure dnsmasq settings
- create/delete/configure dhcp pools
- create/delete/configure static leases
- create/delete/configure ipsets
## Role Variables
| Variable | Descritpion | Status | Type | Example |
| :--- | :--- | :--- | :--- | :--- |
| `dhcp_common` | DHCP and DNS [common options](https://openwrt.org/docs/guide-user/base-system/dhcp#common_options) | | `dictionary` | |
|  `authoritative` | Force dnsmasq into authoritative mode (used if this is the only server on the network) | `required` | `boolean` | `1` |
|  `boguspriv` | Reject reverse lookups to private IP ranges where no corresponding entry exists in `/etc/hosts` | `optional` | `boolean` | `1` |
|  `cachesize` | Size of dnsmasq query cache | `optional` | `integer` | `150` |
|  `domain` | Local domain suffix appended to DHCP names and hosts file entries | `optional` | `string` | `lan` |
|  `domainneeded` | Never forward queries for plain names, without dots or domain parts, to upstream nameservers | `optional` | `boolean` | `1` |
|  `dnssec` | Validate DNS replies and cache DNSSEC data | `optional` | `boolean` | `0` |
|  `dnsseccheckunsigned` | Check the zones of unsigned replies to ensure that unsigned replies are allowed in those zones | `optional` | `boolean` | `0` |
|  `expandhosts` | Add the local domain part to names found in /etc/hosts | `optional` | `boolean` | `1` |
|  `filterwin2k` | Do not forward requests that cannot be answered by public name servers | `optional` | `boolean` | `0` |
|  `fqdn` | Do not resolve unqualifed local hostnames (needs `domain` to be set) | `optional` | `boolean` | `0` |
|  `leasefile` | Path to file to store DHCP leases in | `optional` | `string` | `/tmp/dhcp.leases` |
|  `local` | Never forward matching domains and subdomains, resolve from DHCP or hosts files only. | `optional` | `string` | `/lan/` |
|  `localise_queries` | Return answers to DNS queries matching the subnet from which the query was received if multiple IPs are available | `optional` | `boolean` | `1` |
|  `localservice` | Accept DNS queries only from hosts whose address is on a local subnet | `optional` | `boolean` | `0` |
|  `nonegcache` | Do not cache negative replies, e.g. for non-existent domains | `optional` | `boolean` | `1` |
|  `nonwildcard` | Bind dynamically to interfaces rather than wildcard address | `optional` | `boolean` | `1` |
|  `readethers` | Read static lease entries from /etc/ethers | `optional` | `boolean` | `1` |
|  `rebind_protection` | Enables DNS rebind attack protection by discarding upstream RFC1918 responses | `optional` | `boolean` | `1` |
|  `rebind_localhost` | Allows upstream 127.0.0.0/8 responses, required for DNS based blacklist services (needs `rebind_protection` to be enabled) | `optional` | `boolean` | `1` |
|  `rebind_domain` | List of domains to allow RFC1918 responses for (needs `rebind_protection` to be enabled) | `optional` | `list` | `["/example.com/", "/maydomain.com/"]` |
|  `resolvfile` | Path to file with upstream resolvers | `optional` | `string` | `"/tmp/resolv.conf.d/resolv.conf.auto` |
|  `server` | List of DNS upstream servers to forward requests to | `optional` | `list` | `["192.168.1.1", "192.168.1.2"]` |
|  `serverlist` | Path to file with DNS upstream servers list content | `optional` | `string` | `/etc/dnsmasq.servers` |
|  `address` | List of IP addresses for queried domains | `optional` | `list` | `/site.example.com/192.168.1.1` |
|  `allservers` | Force dnsmasq to send all queries to all available upstream DNS servers | `optional` | `boolean` | `0` |
| `dhcp_pools` | List of per interface [lease pools and settings](https://openwrt.org/docs/guide-user/base-system/dhcp#dhcp_pools) | | `list of dictionaries` | |
|  `id` | Unique dhcp pool ID | `mandatory` | `string` | `lan` |
|  `interface` | Interface associated with DHCP pool (must be one of the interfaces defined in `/etc/config/network`) | `mandatory` | `string` | `lan` |
|  `state` | DHCP pool status (`present` or `absent`) | `required` | `string` | `present` |
|  `dhcp_option` | List of DHCP options | `optional` | `list` | `["3,192.168.1.1", "6,192.168.1.1"]` |
|  `force` | Force DHCP serving on the specified interface even if another DHCP server is detected on the same network segment | `optional` | `boolean` | `0` |
|  `dhcpv4` | Enable or disable DHCPv4 server (`server` or `disabled`) | `mandatory` | `string` | `server` |
|  `leasetime` | Lease time of addresses handed out to client | `required` | `string` | `12h` |
|  `limit` | Size of the address pool | `required` | `integer` | `150` |
|  `start` | Offset from the network address of the underlying interface (for calculating the minimum address that may be leased to clients) | `required` | `integer` | `100` |
|  `ra` | Operation mode of the Router Advertisements service (`server`, `relay`, `hybrid` or `disabled`) | `optional` | `string` | `disabled` |
|  `dhcpv6` | Operation mode of the DHCPv6 service (`server`, `relay`, `hybrid` or `disabled`) | `optional` | `string` | `disabled` |
|  `dns_service` | Enable local IPv6 DNS server | `optional` | `boolean` | `0` |
| `dhcp_leases` | List of hosts' [static leases](https://openwrt.org/docs/guide-user/base-system/dhcp#static_leases) | | `list of dictionaries` | |
|  `id` | Unique dhcp lease ID | `optional` | `string` | `host01` |
|  `name` | Optional hostname to assign to the host | `optional` | `string` | `host01` |
|  `state` | Static lease status (`present` or `absent`) | `required` | `string` | `present` |
|  `ip` | IP address to assign to the host (`IP address` or `ignore`) | `mandatory` | `string` | `192.168.1.11` |
|  `mac` | Hardware address of the host | `mandatory` | `string` | `00:11:22:33:44:55` |
## Dependencies
| Name | Description |
| :--- | :--- |
| `Ansible Role: openwrt` | [Ansible role by gekmihesg](https://github.com/gekmihesg/ansible-openwrt) for managing OpenWRT and derivatives |
## Example Playbook
```yaml
- hosts: openwrt
roles:
- role: flyoverhead.openwrt.dhcp
```
## Example Vars
```yaml
dhcp_common:
authoritative: "1"
boguspriv: "1"
cachesize: "1000"
domainneeded: "1"
rebind_protection: "1"
rebind_localhost: "1"
dhcp_pools:
- id: "lan"
interface: "lan"
state: "state"
dhcpv4: "server"
limit: "50"
start: "50"
dhcp_leases:
- id: "host01"
name: "host01"
state: "present"
ip: "192.168.1.51"
mac: "00:11:22:33:44:55"
```
## License
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.txt)
## Author Information
fly0v3rH34D
## References
- https://openwrt.org/docs/guide-user/base-system/dhcp

View File

@@ -0,0 +1,51 @@
---
# dnsmasq section
dhcp_common:
authoritative: ""
boguspriv: ""
cachesize: ""
domain: ""
domainneeded: ""
dnssec: ""
dnsseccheckunsigned: ""
expandhosts: ""
filterwin2k: ""
fqdn: ""
leasefile: ""
local: ""
localise_queries: ""
localservice: ""
nonegcache: ""
nonwildcard: ""
readethers: ""
rebind_protection: ""
rebind_localhost: ""
rebind_domain: []
resolvfile: ""
server: []
serverlist: ""
address: []
allservers: ""
# dhcp section
dhcp_pools:
- id: ""
interface: ""
state: ""
dhcp_option: []
force: ""
dhcpv4: ""
leasetime: ""
limit: ""
start: ""
ra: ""
dhcpv6: ""
dns_service: ""
# host section
dhcp_leases:
- id: ""
name: ""
state: ""
ip: ""
mac: ""

View File

@@ -0,0 +1,7 @@
---
# Reload dhcp service
- name: Reload dhcp
ansible.builtin.service:
name: "{{ item }}"
state: restarted
loop: ["dnsmasq", "odhcpd"]

12
roles/dhcp/meta/main.yml Normal file
View File

@@ -0,0 +1,12 @@
---
galaxy_info:
author: flyoverhead
description: Configure dhcp settings
license: GPL-3.0
min_ansible_version: "2.13"
platforms:
- name: OpenWrt
versions: ["22.03"]
galaxy_tags: ["openwrt", "dhcp"]
dependencies:
- role: gekmihesg.openwrt

45
roles/dhcp/tasks/dhcp.yml Normal file
View File

@@ -0,0 +1,45 @@
---
# Set state status for dhcp pool
- name: Set state status for dhcp pool {{ item.id | default(item.interface) }}
ansible.builtin.set_fact:
dhcp_state: "{{ item.state | default('present') }}"
# Delete dhcp pool for interface
- name: Delete dhcp pool for interface {{ item.id | default(item.interface) }}
when: "'absent' in dhcp_state"
uci:
command: "absent"
config: "dhcp"
section: "{{ item.id | default(item.interface) }}"
type: "dhcp"
# Create and configure dhcp pool for interface
- name: Create and configure dhcp pool for interface
when: "'present' in dhcp_state"
block:
# Create dhcp pool for interface
- name: Create dhcp pool for interface {{ item.id | default(item.interface) }}
uci:
command: "add"
config: "dhcp"
section: "{{ item.id | default(item.interface) }}"
type: "dhcp"
# Configure dhcp pool
- name: Configure dhcp pool for {{ item.id | default(item.interface) }}
uci:
command: "set"
config: "dhcp"
section: "{{ item.id | default(item.interface) }}"
type: "dhcp"
value:
interface: "{{ item.interface | default(omit) }}"
dhcp_option: "{{ item.dhcp_option | default([]) | join(' ') }}"
force: "{{ item.force | default(omit) }}"
dhcpv4: "{{ item.dhcpv4 | default(omit) }}"
leasetime: "{{ item.leasetime | default(omit) }}"
limit: "{{ item.limit | default(omit) }}"
start: "{{ item.start | default(omit) }}"
ra: "{{ item.ra | default(omit) }}"
dhcpv6: "{{ item.dhcpv6 | default(omit) }}"
dns_service: "{{ item.dns_service | default(omit) }}"

View File

@@ -0,0 +1,34 @@
---
# Configure common options
- name: Configure common options
uci:
command: "set"
config: "dhcp"
section: "@dnsmasq[0]"
type: "dnsmasq"
value:
authoritative: "{{ dhcp_common.authoritative | default(omit) }}"
boguspriv: "{{ dhcp_common.boguspriv | default(omit) }}"
cachesize: "{{ dhcp_common.cachesize | default(omit) }}"
domain: "{{ dhcp_common.domain | default(omit) }}"
domainneeded: "{{ dhcp_common.domainneeded | default(omit) }}"
dnssec: "{{ dhcp_common.dnssec | default(omit) }}"
dnsseccheckunsigned: "{{ dhcp_common.dnsseccheckunsigned | default(omit) }}"
expandhosts: "{{ dhcp_common.expandhosts | default(omit) }}"
filterwin2k: "{{ dhcp_common.filterwin2k | default(omit) }}"
fqdn: "{{ dhcp_common.fqdn | default(omit) }}"
leasefile: "{{ dhcp_common.leasefile | default(omit) }}"
local: "{{ dhcp_common.local | default(omit) }}"
localise_queries: "{{ dhcp_common.localise_queries | default(omit) }}"
localservice: "{{ dhcp_common.localservice | default(omit) }}"
nonegcache: "{{ dhcp_common.nonegcache | default(omit) }}"
nonwildcard: "{{ dhcp_common.nonwildcard | default(omit) }}"
readethers: "{{ dhcp_common.readethers | default(omit) }}"
rebind_protection: "{{ dhcp_common.rebind_protection | default(omit) }}"
rebind_localhost: "{{ dhcp_common.rebind_localhost | default(omit) }}"
rebind_domain: "{{ dhcp_common.rebind_domain | default([]) | join(' ') }}"
resolvfile: "{{ dhcp_common.resolvfile | default([]) | join(' ') }}"
server: "{{ dhcp_common.server | default([]) | join(' ') }}"
serverlist: "{{ dhcp_common.serverlist | default(omit) }}"
address: "{{ dhcp_common.address | default([]) | join(' ') }}"
allservers: "{{ dhcp_common.allservers | default(omit) }}"

40
roles/dhcp/tasks/host.yml Normal file
View File

@@ -0,0 +1,40 @@
---
# Set static lease state status for host
- name: Set static lease state status for host {{ item.id }}
ansible.builtin.set_fact:
static_lease_state: "{{ item.state | default('present') }}"
# Delete static lease for host
- name: Delete static lease for host {{ item.id }}
when: "'absent' in static_lease_state"
uci:
command: "absent"
config: "dhcp"
section: "{{ item.id }}"
type: "host"
# Create and configure static lease for host
- name: Create and configure static lease for host
when: "'present' in static_lease_state"
block:
# Create static lease for host
- name: Create static lease for host {{ item.id }}
uci:
command: "add"
config: "dhcp"
section: "{{ item.id | default('@host[-1]') }}"
type: "host"
# Configure static lease for host
- name: Configure static lease for host {{ item.id }}
uci:
command: "set"
config: "dhcp"
section: "{{ item.id | default('@host[-1]') }}"
type: "host"
value:
name: "{{ item.name | default(omit) }}"
ip: "{{ item.ip | default(omit) }}"
mac: "{{ item.mac | default(omit) }}"
tag: "{{ item.tag | default(omit) }}"
dns: "{{ item.dns | default(omit) }}"

20
roles/dhcp/tasks/main.yml Normal file
View File

@@ -0,0 +1,20 @@
---
# Configure dnsmasq section
- name: Configure dnsmasq section
ansible.builtin.include_tasks: dnsmasq.yml
# Configure dhcp section
- name: Configure dhcp section
ansible.builtin.include_tasks: dhcp.yml
loop: "{{ dhcp_pools | default([]) }}"
# Configure host section
- name: Configure host section
ansible.builtin.include_tasks: host.yml
loop: "{{ dhcp_leases | default([]) }}"
# Apply changes and reload DHCP service
- name: Apply changes and reload dhcp
uci:
command: commit
notify: Reload dhcp