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

91
roles/pbr/README.md Normal file
View File

@@ -0,0 +1,91 @@
# `flyoverhead.openwrt.pbr`
OpenWRT `Policy-Based Routing` configuration
- create and configure pbr rules and routes
## Role Variables
| Variable | Descritpion | Status | Type | Default/Example |
| :--- | :--- | :--- | :--- | :--- |
| `pbr_pkgs` | List of PBR packages to be installed | `required` | `list` | `["pbr", "luci-app-pbr"]` |
| `dnsmasq_full_required_version` | Dnsmasq-full package version required for dnsmasq nft sets support | `required` | `string` | `2.89` |
| `pbr_service` | PBR service configuration settings to be applied | | `dictionary` | |
|  `enabled` | Enable pbr service | `required` | `boolean` | `1` |
|  `verbosity` | Console and system log output verbosity (`0`, `1` or `2`) | `optional` | `integer` | `2` |
|  `strict_enforcement` | Enforce policies when their interface is down | `required` | `boolean` | `1` |
|  `resolver_set` | Resolvers set support for domains (`none`, `adguardhome.ipset`, `dnsmasq.ipset` or `dnsmasq.nftset`) | `required` | `string` | `dnsmasq.nftset` |
|  `resolver_instance` | List of resolvers set support instances (available for `dnsmasq.ipset` and `dnsmasq.nftset`) | `optional` | `string` | `*` |
|  `ipv6_enabled` | Enable IPv6 support | `optional` | `boolean` | `0` |
|  `supported_interface` | List of network interfaces to be explicitly supported by the pbr service | `optional` | `list` | `["lan", "wan"]` |
|  `ignored_interface` | List of network interfaces to be ignored by the pbr service | `optional` | `list` | `["vpnserver", "wgserver"]` |
|  `boot_timeout` | Time in seconds for pbr service to wait for WAN gateway discovery on boot | `optional` | `integer` | `30` |
|  `rule_create_option` | Policy rule creation option (`add` or `insert`) | `required` | `string` | `add` |
|  `icmp_interface` | Default ICMP protocol network interface | `optional` | `string` | `wan` |
|  `wan_mark` | Firewall mark for marks used by the pbr service | `optional` | `string` | `010000` |
|  `fw_mask` | Firewall mask used by the pbr service | `optional` | `string` | `ff0000` |
|  `secure_reload` | Enable killing router traffic (activates killswitch) during service start/restart/reload operations to prevent traffic leaks on unwanted interface (`experimental`) | `optional` | `boolean` | `0` |
|  `webui_show_ignore_target` | Show `ignore` in the list of interfaces | `optional` | `boolean` | `0` |
|  `webui_supported_protocol` | List of protocols to display in the `Protocol` column for policies (`all`, `tcp`, `udp` or `icmp`) | `optional` | `list` | `0` |
| `pbr_policies` | List of PBR policies | | `list of dictionaries` | |
|  `id` | Unique policy ID | `mandatory` | `string` | `example_policy` |
|  `name` | Unique policy name | `mandatory` | `string` | `Example policy` |
|  `state` | Policy status (`present` or `absent`) | `required` | `string` | `present` |
|  `enabled` | Enable policy | `required` | `boolean` | `1` |
|  `interface` | Policy associated network interface | `mandatory` | `string` | `vpn0` |
|  `src_addr` | List of local/source IP addresses, CIDRs, hostnames, mac addresses, local physical devices or URLs to list of addresses (not compatible with the `secure_reload` option) | `required` | `list` | `["192.168.1.0/24"]` |
|  `src_port` | List of space-separated local/source ports or port-ranges | `required` | `list` | `["22", "8000-9000"]` |
|  `dest_addr` | List of remote/target IP addresses, CIDRs, hostnames/domain names or URLs to list of addresses | `required` | `list` | `["192.168.2.0/24"]` |
|  `dest_port` | List of space-separated remote/target ports or port-ranges | `required` | `list` | `["22", "8000-9000"]` |
|  `proto` | Policy protocol (any valid protocol from `/etc/protocols` for CLI/uci or selected from the values set in `webui_supported_protocol`) | `required` | `string` | `auto` |
|  `chain` | Policy chain (`forward`, `input`, `prerouting`, `postrouting` or `output`) | `required` | `string` | `prerouting` |
## 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.pbr
```
## Example Vars
```yaml
pbr_service:
enabled: "1"
verbosity: "0"
strict_enforcement: "0"
resolver_set: "dnsmasq.nftset"
ipv6_enabled: "0"
ignored_interface: ["vpnserver"]
boot_timeout: "30"
rule_create_option: "add"
webui_show_ignore_target: "0"
webui_supported_protocol: ["all", "tcp", "udp", "tcp udp", "icmp"]
pbr_policies:
- id: "example_policy"
name: "Example policy"
state: "present"
enabled: "1"
interface: "vpn0"
dest_addr: ["blocked.example.com", "blocked.com"]
chain: "prerouting"
```
## 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/network/routing/pbr_app
- https://docs.openwrt.melmac.net/pbr/#a-word-about-default-routing

View File

@@ -0,0 +1,39 @@
---
# Policy-Based Routing packages
pbr_pkgs: ["pbr", "luci-app-pbr"]
# Dnsmasq-full required version
dnsmasq_full_required_version: "2.89"
# PBR service configuration
pbr_service:
enabled: ""
verbosity: ""
strict_enforcement: ""
resolver_set: ""
resolver_instance: []
ipv6_enabled: ""
supported_interface: []
ignored_interface: []
boot_timeout: ""
rule_create_option: ""
icmp_interface: ""
wan_mark: ""
fw_mask: ""
secure_reload: ""
webui_show_ignore_target: ""
webui_supported_protocol: []
# PBR policies
pbr_policies:
- id: ""
name: ""
state: ""
enabled: ""
interface: ""
src_addr: []
src_port: []
dest_addr: []
dest_port: []
proto: ""
chain: ""

View File

@@ -0,0 +1,7 @@
---
# Reload pbr service
- name: Reload pbr
ansible.builtin.service:
name: pbr
state: reloaded
enabled: true

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

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

19
roles/pbr/tasks/main.yml Normal file
View File

@@ -0,0 +1,19 @@
---
# Install required packages
- name: Install required packages
ansible.builtin.include_tasks: prepare.yml
# Configure pbr service settings
- name: Configure pbr service settings
ansible.builtin.include_tasks: service.yml
# Configure pbr policies
- name: Configure pbr policies
ansible.builtin.include_tasks: policy.yml
loop: "{{ pbr_policies | default([]) }}"
# Apply changes and reload pbr service
- name: Apply changes and reload pbr
uci:
command: commit
notify: Reload pbr

View File

@@ -0,0 +1,44 @@
---
# Set state status for policy
- name: Set state status for policy {{ item.id | default('@policy[-1]') }}
ansible.builtin.set_fact:
policy_state: "{{ item.state | default('present') }}"
# Delete policy
- name: Delete policy {{ item.id }}
when: "'absent' in policy_state"
uci:
command: "absent"
config: "pbr"
section: "{{ item.id | default('@policy[-1]') }}"
type: "policy"
# Create and configure policy
- name: Create and configure policy
when: "'present' in policy_state"
block:
# Create policy
- name: Create policy {{ item.id | default('@policy[-1]') }}
uci:
command: "add"
config: "pbr"
section: "{{ item.id | default('@policy[-1]') }}"
type: "policy"
# Configure policy
- name: Configure policy {{ item.id | default('@policy[-1]') }}
uci:
command: "set"
config: "pbr"
section: "{{ item.id | default('@policy[-1]') }}"
type: "policy"
value:
name: "{{ item.name | default(omit) }}"
enabled: "{{ item.enabled | default(omit) }}"
interface: "{{ item.interface | default(omit) }}"
src_addr: "{{ item.src_addr | default([]) | join(' ') }}"
src_port: "{{ item.src_port | default([]) | join(' ') }}"
dest_addr: "{{ item.dest_addr | default([]) | join(' ') }}"
dest_port: "{{ item.dest_port | default([]) | join(' ') }}"
proto: "{{ item.proto | default(omit) }}"
chain: "{{ item.chain | default(omit) }}"

View File

@@ -0,0 +1,88 @@
---
# Update opkg cache
- name: Update opkg cache
ansible.builtin.command:
cmd: "opkg update"
changed_when: false
# Install pbr packages
- name: Install pbr packages
opkg:
name: "{{ item }}"
state: "present"
loop: "{{ pbr_pkgs }}"
# Check dnsmasq-full installed version
- name: Check dnsmasq-full installed version
ansible.builtin.command:
cmd: "opkg list-installed | grep dnsmasq-full | awk '{print $3}'"
uses_shell: true
register: dnsmasq_full_installed_version
changed_when: false
# Check dnsmasq-full release version
- name: Check dnsmasq-full release version
ansible.builtin.command:
cmd: "opkg find dnsmasq-full | awk '{print $3}'"
uses_shell: true
register: dnsmasq_full_release_version
changed_when: false
# Install dnsmasq-full release version
- name: Install dnsmasq-full release version
when: >
(dnsmasq_full_installed_version.stdout is undefined or
dnsmasq_full_installed_version.stdout < dnsmasq_full_required_version) and
dnsmasq_full_release_version.stdout >= dnsmasq_full_required_version
block:
# Remove dnsmasq-base packages
- name: Remove dnsmasq-base package
opkg:
name: "{{ item }}"
state: "absent"
loop: ["dnsmasq", "dnsmasq-full"]
# Install dnsmasq-full release version
- name: Install dnsmasq-full release version
opkg:
name: "dnsmasq-full"
state: "present"
# Install dnsmasq-full snapshot version
- name: Install dnsmasq-full snapshot version
when: >
(dnsmasq_full_installed_version.stdout is undefined or
dnsmasq_full_installed_version.stdout < dnsmasq_full_required_version) and
dnsmasq_full_release_version.stdout < dnsmasq_full_required_version
block:
# Remove current dnsmasq-base packages
- name: Remove current dnsmasq packages
opkg:
name: "{{ item }}"
state: "absent"
loop: ["dnsmasq", "dnsmasq-full"]
# Install curl for package downloading
- name: Install curl
opkg:
name: "curl"
state: "present"
# Get current package architecture
- name: Get current package architecture
ansible.builtin.command:
cmd: "opkg print-architecture | tail -n 1 | awk '{print $2}'"
uses_shell: true
register: current_package_architecture
changed_when: false
# Set snapshot packages facts
- name: Set snapshot packages facts
ansible.builtin.set_fact:
snapshot_repo_url: "https://downloads.openwrt.org/snapshots/packages/{{ current_package_architecture.stdout }}/base/"
snapshot_pkgs_list: ["libubox[0-9]", "libubus[0-9]", "dnsmasq-full"]
# Download and install snapshot packages
- name: Download and install snapshot packages
ansible.builtin.include_tasks: snapshot.yml
loop: "{{ snapshot_pkgs_list }}"

View File

@@ -0,0 +1,25 @@
---
# Configure service settings
- name: Configure service settings
uci:
command: "set"
config: "pbr"
section: "config"
type: "pbr"
value:
enabled: "{{ pbr_service.enabled | default(omit) }}"
verbosity: "{{ pbr_service.verbosity | default(omit) }}"
strict_enforcement: "{{ pbr_service.strict_enforcement | default(omit) }}"
resolver_set: "{{ pbr_service.resolver_set | default(omit) }}"
resolver_instance: "{{ pbr_service.resolver_instance | default([]) | join(' ') }}"
ipv6_enabled: "{{ pbr_service.ipv6_enabled | default(omit) }}"
supported_interface: "{{ pbr_service.supported_interface | default([]) | join(' ') }}"
ignored_interface: "{{ pbr_service.ignored_interface | default([]) | join(' ') }}"
boot_timeout: "{{ pbr_service.boot_timeout | default(omit) }}"
rule_create_option: "{{ pbr_service.rule_create_option | default(omit) }}"
icmp_interface: "{{ pbr_service.icmp_interface | default(omit) }}"
wan_mark: "{{ pbr_service.wan_mark | default(omit) }}"
fw_mask: "{{ pbr_service.fw_mask | default(omit) }}"
secure_reload: "{{ pbr_service.secure_reload | default(omit) }}"
webui_show_ignore_target: "{{ pbr_service.webui_show_ignore_target | default(omit) }}"
webui_supported_protocol: "{{ pbr_service.webui_supported_protocol | default([]) | join(' ') }}"

View File

@@ -0,0 +1,32 @@
---
# Get package file name
- name: Get package file name {{ item }}
ansible.builtin.command:
cmd: 'curl {{ snapshot_repo_url }} | grep {{ item }} | sed ''s/.*href=\"//'' | sed -r ''s/\".+//'''
uses_shell: true
register: snapshot_package_file_name
changed_when: false
# Set package file name fact
- name: Set package file name fact
ansible.builtin.set_fact:
snapshot_package_name: "{{ snapshot_package_file_name.stdout }}"
# Download package file
- name: Download package file {{ snapshot_package_name }}
ansible.builtin.command:
cmd: "curl {{ snapshot_repo_url }}{{ snapshot_package_name }} -o {{ snapshot_package_name }}"
uses_shell: true
chdir: "/tmp"
# Install package file
- name: Install package from file {{ snapshot_package_name }}
ansible.builtin.command:
cmd: "opkg install {{ snapshot_package_name }}"
chdir: "/tmp"
# Clean package file
- name: Clean package file {{ snapshot_package_name }}
ansible.builtin.command:
cmd: "rm -f {{ snapshot_package_name }}"
chdir: "/tmp"