Initial commit
This commit is contained in:
91
roles/pbr/README.md
Normal file
91
roles/pbr/README.md
Normal 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` | Resolver’s set support for domains (`none`, `adguardhome.ipset`, `dnsmasq.ipset` or `dnsmasq.nftset`) | `required` | `string` | `dnsmasq.nftset` |
|
||||
|  `resolver_instance` | List of resolver’s 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
|
||||
39
roles/pbr/defaults/main.yml
Normal file
39
roles/pbr/defaults/main.yml
Normal 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: ""
|
||||
7
roles/pbr/handlers/main.yml
Normal file
7
roles/pbr/handlers/main.yml
Normal 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
12
roles/pbr/meta/main.yml
Normal 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
19
roles/pbr/tasks/main.yml
Normal 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
|
||||
44
roles/pbr/tasks/policy.yml
Normal file
44
roles/pbr/tasks/policy.yml
Normal 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) }}"
|
||||
88
roles/pbr/tasks/prepare.yml
Normal file
88
roles/pbr/tasks/prepare.yml
Normal 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 }}"
|
||||
25
roles/pbr/tasks/service.yml
Normal file
25
roles/pbr/tasks/service.yml
Normal 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(' ') }}"
|
||||
32
roles/pbr/tasks/snapshot.yml
Normal file
32
roles/pbr/tasks/snapshot.yml
Normal 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"
|
||||
Reference in New Issue
Block a user