flyoverhead / ansible-openwrt

Ansible collection for automative configuration of OpenWrt devices (without Python).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ansible Collection - flyoverhead.openwrt

Ansible collection for automative configuration of OpenWrt devices (without Python).

Compatibilities

This collection was tested on

Supported OS

  • OpenWrt 22.03

Installation and Usage

Requirements

  • Ansible >=2.13

  • Task >=3.20

Installation

Cloning repo:

git clone https://github.com/flyoverhead/ansible-openwrt

Installing requirements:

cd ansible-openwrt
ansible-galaxy collection install -r requirements.yml

Roles usage

Full documentation and usage examples of role <role> can be found in roles/<role>/README.md.

Example Playbook

playbook.yml
---
- name: Configure openwrt
  hosts: openwrt
  ignore_unreachable: true
  gather_facts: false
  tags: configure_openwrt

  pre_tasks:
    - name: Update package cache
      ansible.builtin.command:
        cmd: "opkg update"
      changed_when: false

  roles:
    - extroot
    - system
    - network
    - batman
    - wireless
    - wireguard
    - firewall
    - pbr
    - dropbear
    - dhcp

  post_tasks:
    - name: Reboot device
      ansible.builtin.command:
        cmd: "reboot"
      changed_when: false

For gekmihesg.openwrt role works properly it is mandatory to use openwrt as a hosts group name. More details can be found at gekmihesg/ansible-openwrt#ansible-role-openwrt.

Example Variables

Description
Example configuration for `TP-Link Archer C7` and `MikroTik hAP ac²`
  • Enable extroot for external USB device
  • Create network for IoT devices (IOT) isolated from LAN
  • Disable WAN IPv6 network interface
  • Create B.A.T.M.A.N. mesh network interfaces
  • Separate mesh networks (LAN and IOT) by mapping VLAN ports (bat0.2 and bat0.3)
  • Delete default WIFI APs
  • Create WIFI mesh interface for mesh nodes (server) communication
  • Create WIFI APs for LAN (5GHz only) and IOT (both 2.4Ghz and 5GHz) networks with fast BSS transition (802.11r) support
  • Configure Dnsmasq and DHCP with static leases for example LAN and IOT clients
  • Create Wireguard interface for remote access to the router from the Internet with peers
  • Create Wireguard interface for access to remote VPS server (for VPN routing)
  • Configure firewall zones, zone forwardings, rules and redirects
  • Configure Policy-Based routing for example domains to remote VPS server

host_vars
archer.yml
# Device subnet
device_ip_address: "192.168.1.1"
device_dhcp_start: "50"

# Device LAN bridge port
device_bridge_port: "eth0.1"

# Device WIFI radios
device_5g_radio: "radio1"
device_2g_radio: "radio0"

# Wireguard Home port
wireguard_home_port: "51820"

# Wireguard VPS address
wireguard_vps_address: "10.0.0.2"

# Enable extroot
extroot_enabled: true

# Configure system settings
system:
  hostname: "archer"
  description: "TP-Link Archer C7 AC1750"
  timezone: "UTC"
  zonename: "UTC"
mikrotik.yml
# Device subnet
device_ip_address: "192.168.1.2"
device_dhcp_start: "100"

# Device LAN bridge port
device_bridge_port: "eth0"

# Device WIFI radios
device_5g_radio: "radio1"
device_2g_radio: "radio0"

# Wireguard Home port
wireguard_home_port: "51821"

# Wireguard VPS address
wireguard_vps_address: "10.0.0.3"

# Enable extroot
extroot_enabled: true

# Configure system settings
system:
  hostname: "mikrotik"
  description: "MikroTik hAP ac2"
  timezone: "UTC"
  zonename: "UTC"

group_vars
openwrt.yml
# Configure WIFI
wifi_password: "passowrd"

# Configure Wireguard VPS
wireguard_server_public_key: "public_key"
wireguard_server_preshared_key: "preshared_key"
wireguard_server_address: "address"
wireguard_server_port: "port"

# Configure network devices
network_devices:
  - id: "@device[0]"
    name: "br-lan"
    state: "present"
    type: "bridge"
    ports: ["{{ device_bridge_port }}", "bat0.2"]
    stp: "1"
    igmp_snooping: "1"
    ipv6: "0"
  - id: "iot_dev"
    name: "br-iot"
    state: "present"
    type: "bridge"
    ports: ["bat0.3"]
    stp: "1"
    igmp_snooping: "1"
    ipv6: "0"

# Configure network interfaces
network_interfaces:
  - id: "lan"
    state: "present"
    device: "br-lan"
    proto: "static"
    auto: "1"
    force_link: "1"
    ipaddr: "{{ device_ip_address }}"
    netmask: "255.255.255.0"
    mtu: "1536"
    ipv6: "0"
    delegate: "0"
  - id: "wan"
    state: "present"
    proto: "dhcp"
    auto: "1"
    force_link: "1"
    peerdns: "0"
    dns: ["1.1.1.1", "9.9.9.9"]
    ipv6: "0"
    delegate: "0"
  - id: "iot"
    state: "present"
    device: "br-iot"
    proto: "static"
    auto: "1"
    force_link: "1"
    ipaddr: "{{ device_ip_address | ansible.utils.ipmath(2560) }}"
    netmask: "255.255.255.0"
    mtu: "1536"
    ipv6: "0"
    delegate: "0"
  - id: "wan6"
    state: "absent"

# Configure batman mesh network
batman_enabled: true
ath10k_ct_fix: true

batman_network_interfaces:
  - id: "bat0"
    state: "present"
    proto: "batadv"
    routing_algo: "BATMAN_IV"
    fragmentation: "1"
    gw_mode: "server"
    bridge_loop_avoidance: "1"
    distributed_arp_table: "1"
    multicast_mode: "1"
    hop_penalty: "30"
    delegate: "0"
  - id: "batmesh"
    state: "present"
    proto: "batadv_hardif"
    master: "bat0"
    mtu: "2304"
    delegate: "0"

batman_wireless_interfaces:
  - id: "mesh"
    name: "mesh"
    state: "present"
    device: "{{ device_5g_radio }}"
    network: ["batmesh"]
    mode: "mesh"
    mesh_id: "mesh"
    mesh_fwding: "0"
    encryption: "sae"
    key: "{{ wifi_password }}"
    disabled: "0"

# Configure wireless network
wireless_devices:
  - id: "{{ device_5g_radio }}"
    type: "mac80211"
    channel: "44"
    htmode: "VHT80"
    disabled: "0"
  - id: "{{ device_2g_radio }}"
    type: "mac80211"
    channel: "1"
    htmode: "VHT40"
    disabled: "0"

wireless_interfaces:
  - id: "lan5"
    name: "wlan5"
    state: "present"
    device: "{{ device_5g_radio }}"
    network: ["lan"]
    mode: "ap"
    ssid: "lan5"
    encryption: "sae-mixed"
    key: "{{ wifi_password }}"
    ieee80211r: "1"
    mobility_domain: "1"
    ft_over_ds: "1"
    ft_psk_generate_local: "1"
    disabled: "0"
  - id: "iot5"
    name: "wiot5"
    state: "present"
    device: "{{ device_5g_radio }}"
    network: ["iot"]
    mode: "ap"
    ssid: "iot5"
    encryption: "sae-mixed"
    key: "{{ wifi_password }}"
    ieee80211r: "1"
    mobility_domain: "1"
    ft_over_ds: "1"
    ft_psk_generate_local: "1"
    disabled: "0"
  - id: "iot2"
    name: "wiot2"
    state: "present"
    device: "{{ device_2g_radio }}"
    network: ["iot"]
    mode: "ap"
    ssid: "iot2"
    encryption: "sae-mixed"
    key: "{{ wifi_password }}"
    ieee80211r: "1"
    mobility_domain: "1"
    ft_over_ds: "1"
    ft_psk_generate_local: "1"
    disabled: "0"
  - id: "default_radio0"
    state: "absent"
  - id: "default_radio1"
    state: "absent"

# Configure dnsmasq and dhcp
dhcp_common:
  authoritative: "1"
  boguspriv: "1"
  cachesize: "1000"
  domainneeded: "1"
  dnssec: "1"
  dnsseccheckunsigned: "1"
  filterwin2k: "1"
  rebind_protection: "1"
  rebind_localhost: "1"
  server: ["1.1.1.1", "9.9.9.9"]
  allservers: "1"
  localservice: "0"
  nonegcache: "1"

dhcp_pools:
  - interface: "lan"
    state: "present"
    force: "1"
    dhcpv4: "server"
    limit: "50"
    start: "{{ device_dhcp_start }}"
    ra: "disabled"
    dhcpv6: "disabled"
    dns_service: "0"
  - interface: "iot"
    state: "present"
    force: "1"
    dhcpv4: "server"
    limit: "50"
    start: "{{ device_dhcp_start }}"
    ra: "disabled"
    dhcpv6: "disabled"
    dns_service: "0"

dhcp_leases:
  - id: "host01"
    name: "host01"
    state: "present"
    mac: "00:11:22:33:44:55"
  - id: "host02"
    name: "host02"
    state: "present"
    mac: "55:44:33:22:11:00"

# Configure wireguard interfaces
wireguard_interfaces:
  - id: "wg_home"
    state: "present"
    proto: "wireguard"
    addresses: "{{ device_ip_address | ansible.utils.ipmath(5120) }}"
    listen_port: "{{ wireguard_home_port }}"
    peers: ["peer01", "peer02"]
  - id: "wg_remote"
    state: "present"
    proto: "wireguard"
    addresses: "{{ wireguard_vps_address }}"

# Configure wireguard peers
wireguard_peers:
  - id: "vps"
    name: "VPS"
    state: "present"
    public_key: "{{ wireguard_server_public_key }}"
    preshared_key: "{{ wireguard_server_preshared_key }}"
    endpoint_host: "{{ wireguard_server_address }}"
    endpoint_port: "{{ wireguard_server_port }}"
    route_allowed_ips: "0"
    persistent_keepalive: "25"
    allowed_ips: ["0.0.0.0/0"]
    wireguard_interface_name: "wg_remote"

# Configure firewall
firewall_defaults:
  input: "ACCEPT"
  forward: "REJECT"
  output: "ACCEPT"
  drop_invalid: "1"
  synflood_protect: "1"
  flow_offloading: "1"
  flow_offloading_hw: "1"

firewall_zones:
  - id: "@zone[0]"
    name: "lan"
    state: "present"
    network: ["lan", "wg_home"]
    input: "ACCEPT"
    forward: "ACCEPT"
    output: "ACCEPT"
    family: "ipv4"
  - id: "iot"
    name: "iot"
    state: "present"
    network: ["iot"]
    input: "DROP"
    forward: "DROP"
    output: "ACCEPT"
    family: "ipv4"
  - id: "@zone[1]"
    name: "wan"
    state: "present"
    network: ["wan", "wg_remote"]
    masq: "1"
    mtu_fix: "1"
    input: "DROP"
    forward: "DROP"
    output: "ACCEPT"
    family: "ipv4"

firewall_forwardings:
  - id: "lan_iot"
    state: "present"
    src: "lan"
    dest: "iot"
    family: "ipv4"
  - id: "iot_wan"
    state: "present"
    src: "iot"
    dest: "wan"
    family: "ipv4"

firewall_rules:
  - id: "allow_iot_dhcp_dns"
    name: "Allow DHCP and DNS for IoT network"
    state: "present"
    src: "iot"
    dest_port: ["53", "67", "68"]
    target: "ACCEPT"
    family: "ipv4"
  - id: "wg_home_access"
    name: "Allow remote access to Wireguard home server"
    state: "present"
    src: "wan"
    dest_port: ["{{ wireguard_home_port }}"]
    target: "ACCEPT"
    proto: ["udp"]
    family: "ipv4"

firewall_redirects:
  - id: "force_dns_lan"
    name: "Force DNS for LAN network"
    state: "present"
    src: "lan"
    src_dport: "53"
    target: "DNAT"
    family: "ipv4"
  - id: "force_dns_iot"
    name: "Force DNS for IoT network"
    state: "present"
    src: "iot"
    src_dport: "53"
    target: "DNAT"
    family: "ipv4"

# Configure policy-based routing
pbr_service:
  enabled: "1"
  verbosity: "0"
  strict_enforcement: "0"
  resolver_set: "dnsmasq.nftset"
  ipv6_enabled: "0"
  ignored_interface: ["wg_home"]
  boot_timeout: "30"
  rule_create_option: "add"
  webui_show_ignore_target: "0"
  webui_supported_protocol: ["all", "tcp", "udp", "tcp udp", "icmp"]

pbr_policies:
  - id: "instagram"
    name: "Instagram"
    state: "present"
    enabled: "1"
    interface: "wg_remote"
    dest_addr:
      [
        "129.134.0.0/16",
        "179.60.0.0/16",
        "185.60.0.0/16",
        "185.199.0.0/16",
        "31.13.0.0/16",
        "157.240.0.0/16",
        "instagram.com",
      ]
    chain: "prerouting"

# Configure dropbear
dropbear:
  enable: "1"
  verbose: "0"
  PasswordAuth: "1"
  Port: "22"
  RootPasswordAuth: "1"
  RootLogin: "1"
  Interface: "lan"
  keyfile: "/etc/dropbear/authorized_keys"
  mdns: "0"
  MaxAuthTries: "3"

Included content

Roles

Name Description
flyoverhead.openwrt.batman Ansible role for OpenWrt B.A.T.M.A.N. mesh network configuration
flyoverhead.openwrt.dhcp Ansible role for OpenWrt dhcp configuration
flyoverhead.openwrt.dropbear Ansible role for OpenWrt dropbear configuration
flyoverhead.openwrt.extroot Ansible role for OpenWrt extroot configuration
flyoverhead.openwrt.firewall Ansible role for OpenWrt firewall configuration
flyoverhead.openwrt.mesh11sd Ansible role for OpenWrt 802.11s mesh network configuration
flyoverhead.openwrt.network Ansible role for OpenWrt network configuration
flyoverhead.openwrt.pbr Ansible role for OpenWrt Policy-Based Routing configuration
flyoverhead.openwrt.system Ansible role for OpenWrt system configuration
flyoverhead.openwrt.wireguard Ansible role for OpenWrt wireguard configuration
flyoverhead.openwrt.wireless Ansible role for OpenWrt wireless configuration

Testing

Device(s) can be defined in tests/inventory.yml

All required variables should be defined (according to inventory.yml) in:

  • tests/group_vars/openwrt.yml
  • tests/host_vars/archer.yml
  • tests/host_vars/mikrotik.yml

Test can be launched from the root directory of the collection by running:

task test

License

  • GPL-3.0-only

Author Information

fLy0v3rH34d

TODO

If you like the project please feel free to support further development

Bitcoin Ethereum
bc1qrc8etpf4a7a50a0mfjyfv6fkzcg0qn3jmv882u 0x5b872a332C94006F0f8A032D8a5D799E1668bf9e
drawing drawing

About

Ansible collection for automative configuration of OpenWrt devices (without Python).