├── tests ├── inventory └── test.yml ├── handlers └── main.yml ├── defaults ├── main.yml └── example_vars.yml ├── tasks └── main.yml ├── README.md ├── meta └── main.yml ├── vars └── main.yml └── templates └── er_config.j2 /tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for richardhofman.edgeos_router -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - richardhofman.edgeos_router -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for richardhofman.edgeos_router 3 | - include_vars: 4 | file: example_vars.yml 5 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for richardhofman.edgeos_router 3 | - name: Generate configuration file. 4 | local_action: 5 | template: 6 | src: er_config.j2 7 | dest: /tmp/er_config.txt 8 | 9 | - name: Push configuration to router. 10 | edgeos_config: 11 | backup: yes 12 | src: /tmp/er_config.txt 13 | 14 | - name: Delete config file. 15 | local_action: 16 | file: 17 | path: /tmp/er_config.txt 18 | state: absent 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Important 2 | ========= 3 | 4 | This role is still in development and not all functionality will necessarily work - use/play with this at your own risk! 5 | 6 | EdgeOS_Router 7 | ========= 8 | 9 | This role configures an EdgeOS router, generating configuration entries for firewall rulesets and rules, network interfaces (LAN), network services (DHCP, DNS), and PPPoE WAN. It uses the `edgeos_config` module, introduced in Ansible 2.5, to apply the 10 | configuration to a target EdgeOS appliance. 11 | 12 | Requirements 13 | ------------ 14 | 15 | N/A 16 | 17 | Role Variables 18 | -------------- 19 | 20 | Configuration is generated from a dictionary containing different sections for various aspects of the EdgeOS feature set. An example dictionary is defined in the `vars/` directory. 21 | 22 | The configuration must always be passed to the role as the `config` variable. 23 | 24 | Dependencies 25 | ------------ 26 | 27 | N/A 28 | 29 | Example Playbook 30 | ---------------- 31 | 32 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: 33 | 34 | - hosts: servers 35 | roles: 36 | - { role: username.rolename, config: edgerouter_config } 37 | 38 | License 39 | ------- 40 | 41 | MIT 42 | 43 | Author Information 44 | ------------------ 45 | 46 | Richard Hofman (richard@hofman.co.nz // @rho_nz // [rho.nz](https://rho.nz)) -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Richard Hofman 3 | description: Role for generating and applying configuration for EdgeOS router. 4 | 5 | # If the issue tracker for your role is not on github, uncomment the 6 | # next line and provide a value 7 | # issue_tracker_url: http://example.com/issue/tracker 8 | 9 | # Some suggested licenses: 10 | # - BSD (default) 11 | # - MIT 12 | # - GPLv2 13 | # - GPLv3 14 | # - Apache 15 | # - CC-BY 16 | license: MIT 17 | 18 | min_ansible_version: 2.5 19 | 20 | # If this a Container Enabled role, provide the minimum Ansible Container version. 21 | # min_ansible_container_version: 22 | 23 | # Optionally specify the branch Galaxy will use when accessing the GitHub 24 | # repo for this role. During role install, if no tags are available, 25 | # Galaxy will use this branch. During import Galaxy will access files on 26 | # this branch. If Travis integration is configured, only notifications for this 27 | # branch will be accepted. Otherwise, in all cases, the repo's default branch 28 | # (usually master) will be used. 29 | #github_branch: 30 | 31 | # 32 | # platforms is a list of platforms, and each platform has a name and a list of versions. 33 | # 34 | # platforms: 35 | # - name: Fedora 36 | # versions: 37 | # - all 38 | # - 25 39 | # - name: SomePlatform 40 | # versions: 41 | # - all 42 | # - 1.0 43 | # - 7 44 | # - 99.99 45 | 46 | galaxy_tags: [] 47 | # List tags for your role here, one per line. A tag is a keyword that describes 48 | # and categorizes the role. Users find roles by searching for tags. Be sure to 49 | # remove the '[]' above, if you add tags to this list. 50 | # 51 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 52 | # Maximum 20 tags per role. 53 | 54 | dependencies: [] 55 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 56 | # if you add dependencies to this list. -------------------------------------------------------------------------------- /defaults/example_vars.yml: -------------------------------------------------------------------------------- 1 | config: 2 | time_zone: Pacific/Auckland 3 | hostname: router 4 | unms_mgmt_enabled: false 5 | offloading: 6 | hwnat: true 7 | ipsec: true 8 | 9 | ssh: 10 | port: 22 11 | version: v2 12 | 13 | gui: 14 | http_port: 80 15 | https_port: 443 16 | weak_cipher_support: false 17 | 18 | # If no Dynamic DNS service is needed, comment this section out. 19 | dynamic_dns: 20 | interface: pppoe0 21 | service_type: custom-noip 22 | hostname: example.com 23 | login: joe 24 | password: examplePassW**d? 25 | protocol: noip 26 | 27 | dns_forwarder: 28 | cache_size: 150 29 | 30 | users: 31 | - username: joe 32 | full_name: "Joe Bloggs" 33 | encrypted_password: "" # for systems where the password is already stored. 34 | plaintext_password: "anotherP**sword!!0" # for users that need to be created upon provisioning. 35 | level: "admin" 36 | 37 | ntp: 38 | - 0.ubnt.pool.ntp.org 39 | - 1.ubnt.pool.ntp.org 40 | - 2.ubnt.pool.ntp.org 41 | - 3.ubnt.pool.ntp.org 42 | 43 | firewall: 44 | global: 45 | all_ping: true 46 | broadcast_ping: false 47 | ipv6_receive_redirects: false 48 | ipv6_src_route: false 49 | ip_src_route: false 50 | log_martians: true 51 | mss_clamp: 1412 52 | receive_redirects: false 53 | send_redirects: true 54 | source_validation: false 55 | syn_cookies: true 56 | 57 | rulesets: 58 | - name: WAN_IN 59 | default_action: drop 60 | description: WAN to internal 61 | rules: 62 | - number: 10 63 | description: Allow related/established 64 | action: accept 65 | states: 66 | - established 67 | - related 68 | - number: 20 69 | action: drop 70 | description: Drop invalid state 71 | states: 72 | - invalid 73 | - name: WAN_LOCAL 74 | default_action: drop 75 | description: WAN to router 76 | rules: 77 | - number: 10 78 | action: accept 79 | description: Allow related/established 80 | states: 81 | - established 82 | - related 83 | - number: 20 84 | action: drop 85 | description: Drop invalid state 86 | states: 87 | - invalid 88 | 89 | # If no WAN interface is desired, comment this section out. 90 | pppoe_interface: 91 | name: eth4 92 | duplex: auto 93 | speed: auto 94 | vlan_id: 999 # comment this line if no VLAN on the PPPoE interface. 95 | mtu: 1492 96 | 97 | userid: "joebloggs@isp.net" 98 | password: 1234567890 99 | 100 | nat_masquerade: true 101 | auto_firewall: true 102 | hairpin_nat: true 103 | 104 | default_route: auto 105 | nameserver: auto 106 | firewall_in_ruleset: WAN_IN 107 | firewall_local_ruleset: WAN_LOCAL 108 | 109 | # These won't be applied if no WAN (PPPoE) interface is specified. 110 | port_forwards: 111 | - description: Example Port Forward 112 | to_addr: 10.0.10.90 113 | to_port: 8443 114 | public_port: 443 115 | protocol: tcp_udp # tcp, udp or tcp_udp. 116 | 117 | # LAN networks - multiple can be defined, but only one network per interface! 118 | networks: 119 | - name: ExampleLAN # "shared network name" used for DHCP/system variable names. 120 | cidr_block: 10.0.0.0/16 # 121 | mtu: 1500 # 122 | vlans_enabled: false # 123 | router_addr: "10.0.0.1/16" # must include CIDR block (e.g. /24) 124 | 125 | interfaces: # If >1 assigned interface, switch is automatically created. 126 | - "eth0" # 127 | - "eth1" # 128 | - "eth2" # 129 | - "eth3" # 130 | 131 | dhcp: 132 | def_gateway: 10.0.0.1 133 | nameserver: 10.0.0.1 134 | lease_ttl: 86400 135 | start: 10.0.0.10 136 | end: 10.0.255.254 137 | 138 | dhcp_static_leases: 139 | - name: Example-DHCP-Reservation 140 | ip_addr: 10.0.10.90 141 | mac_addr: aa:bb:cc:00:1d:c3 142 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for richardhofman.edgeos_router 3 | config: 4 | time_zone: Pacific/Auckland 5 | hostname: router 6 | unms_mgmt_enabled: false 7 | offloading: 8 | hwnat: true 9 | ipsec: true 10 | 11 | ssh: 12 | port: 22 13 | version: v2 14 | 15 | gui: 16 | http_port: 80 17 | https_port: 443 18 | weak_cipher_support: false 19 | 20 | # If no Dynamic DNS service is needed, comment this section out. 21 | dynamic_dns: 22 | interface: pppoe0 23 | service_type: custom-noip 24 | hostname: example.com 25 | login: joe 26 | password: examplePassW**d? 27 | protocol: noip 28 | 29 | dns_forwarder: 30 | cache_size: 150 31 | 32 | users: 33 | - username: joe 34 | full_name: "Joe Bloggs" 35 | encrypted_password: "" # for systems where the password is already stored. 36 | plaintext_password: "anotherP**sword!!0" # for users that need to be created upon provisioning. 37 | level: "admin" 38 | 39 | ntp: 40 | - 0.ubnt.pool.ntp.org 41 | - 1.ubnt.pool.ntp.org 42 | - 2.ubnt.pool.ntp.org 43 | - 3.ubnt.pool.ntp.org 44 | 45 | firewall: 46 | global: 47 | all_ping: true 48 | broadcast_ping: false 49 | ipv6_receive_redirects: false 50 | ipv6_src_route: false 51 | ip_src_route: false 52 | log_martians: true 53 | mss_clamp: 1412 54 | receive_redirects: false 55 | send_redirects: true 56 | source_validation: false 57 | syn_cookies: true 58 | 59 | rulesets: 60 | - name: WAN_IN 61 | default_action: drop 62 | description: WAN to internal 63 | rules: 64 | - number: 10 65 | description: Allow related/established 66 | action: accept 67 | states: 68 | - established 69 | - related 70 | - number: 20 71 | action: drop 72 | description: Drop invalid state 73 | states: 74 | - invalid 75 | - name: WAN_LOCAL 76 | default_action: drop 77 | description: WAN to router 78 | rules: 79 | - number: 10 80 | action: accept 81 | description: Allow related/established 82 | states: 83 | - established 84 | - related 85 | - number: 20 86 | action: drop 87 | description: Drop invalid state 88 | states: 89 | - invalid 90 | 91 | # If no WAN interface is desired, comment this section out. 92 | pppoe_interface: 93 | name: eth4 94 | duplex: auto 95 | speed: auto 96 | vlan_id: 999 # comment this line if no VLAN on the PPPoE interface. 97 | mtu: 1492 98 | 99 | userid: "joebloggs@isp.net" 100 | password: 1234567890 101 | 102 | nat_masquerade: true 103 | auto_firewall: true 104 | hairpin_nat: true 105 | 106 | default_route: auto 107 | nameserver: auto 108 | firewall_in_ruleset: WAN_IN 109 | firewall_local_ruleset: WAN_LOCAL 110 | 111 | # These won't be applied if no WAN (PPPoE) interface is specified. 112 | port_forwards: 113 | - description: Example Port Forward 114 | to_addr: 10.0.10.90 115 | to_port: 8443 116 | public_port: 443 117 | protocol: tcp_udp # tcp, udp or tcp_udp. 118 | 119 | # LAN networks - multiple can be defined, but only one network per interface! 120 | networks: 121 | - name: ExampleLAN # "shared network name" used for DHCP/system variable names. 122 | cidr_block: 10.0.0.0/16 # 123 | mtu: 1500 # 124 | vlans_enabled: false # 125 | router_addr: "10.0.0.1/16" # must include CIDR block (e.g. /24) 126 | 127 | interfaces: # If >1 assigned interface, switch is automatically created. 128 | - "eth0" # 129 | - "eth1" # 130 | - "eth2" # 131 | - "eth3" # 132 | 133 | dhcp: 134 | def_gateway: 10.0.0.1 135 | nameserver: 10.0.0.1 136 | lease_ttl: 86400 137 | start: 10.0.0.10 138 | end: 10.0.255.254 139 | 140 | dhcp_static_leases: 141 | - name: Example-DHCP-Reservation 142 | ip_addr: 10.0.10.90 143 | mac_addr: aa:bb:cc:00:1d:c3 144 | -------------------------------------------------------------------------------- /templates/er_config.j2: -------------------------------------------------------------------------------- 1 | # Set up basic firewall requirements. 2 | set firewall all-ping {{ "enable" if config.firewall.global.all_ping else "disable" }} 3 | set firewall broadcast-ping {{ "enable" if config.firewall.global.broadcast_ping else "disable" }} 4 | set firewall ipv6-receive-redirects {{ "enable" if config.firewall.global.ipv6_receive_redirects else "disable" }} 5 | set firewall ipv6-src-route {{ "enable" if config.firewall.global.ipv6_src_route else "disable" }} 6 | set firewall ip-src-route {{ "enable" if config.firewall.global.ip_src_route else "disable" }} 7 | set firewall log-martians {{ "enable" if config.firewall.global.log_martians else "disable" }} 8 | 9 | set firewall options mss-clamp mss {{ config.firewall.global.mss_clamp }} 10 | set firewall receive-redirects {{ "enable" if config.firewall.global.receive_redirects else "disable" }} 11 | set firewall send-redirects {{ "enable" if config.firewall.global.send_redirects else "disable" }} 12 | set firewall source-validation {{ "enable" if config.firewall.global.source_validation else "disable" }} 13 | set firewall syn-cookies {{ "enable" if config.firewall.global.syn_cookies else "disable" }} 14 | 15 | # ==== Set up firewall rulesets ==== # 16 | {% if config.firewall.rulesets is defined %} 17 | {% for ruleset in config.firewall.rulesets %} 18 | set firewall name {{ ruleset.name }} default-action {{ ruleset.default_action }} 19 | set firewall name {{ ruleset.name }} description '{{ ruleset.description }}' 20 | {% for rule in ruleset.rules %} 21 | set firewall name {{ ruleset.name }} rule {{ rule.number }} action {{ rule.action }} 22 | set firewall name {{ ruleset.name }} rule {{ rule.number }} description '{{ rule.description }}' 23 | {% for state in rule.states %} 24 | set firewall name {{ ruleset.name }} rule {{ rule.number }} state {{ state }} enable 25 | {% endfor %} 26 | {% endfor %} 27 | {% endfor %} 28 | {% endif %} 29 | 30 | # ==== Configure interfaces ==== # 31 | {% if config.pppoe_interface is defined %} 32 | # -- WAN interface (currently PPPoE only) -- # 33 | set interfaces ethernet {{ config.pppoe_interface.name }} duplex {{ config.pppoe_interface.duplex }} 34 | set interfaces ethernet {{ config.pppoe_interface.name }} speed {{ config.pppoe_interface.speed }} 35 | 36 | {% if config.pppoe_interface.vlan_id is defined %} 37 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} description 'WAN (PPPoE)' 38 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 default-route {{ config.pppoe_interface.default_route }} 39 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 firewall in name {{ config.pppoe_interface.firewall_in_ruleset }} 40 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 firewall local name {{ config.pppoe_interface.firewall_local_ruleset }} 41 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 mtu {{ config.pppoe_interface.mtu }} 42 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 name-server {{ config.pppoe_interface.nameserver }} 43 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 password {{ config.pppoe_interface.password }} 44 | set interfaces ethernet {{ config.pppoe_interface.name }} vif {{ config.pppoe_interface.vlan_id }} pppoe 0 user-id {{ config.pppoe_interface.userid }} 45 | {% else %} 46 | # -- Todo: configure direct PPPoE interface here -- # 47 | {% endif %} 48 | 49 | # -- Set up NAT/port forwarding -- # 50 | {% if config.pppoe_interface.nat_masquerade %} 51 | set service nat rule 5010 description 'masquerade for WAN' 52 | set service nat rule 5010 outbound-interface pppoe0 53 | set service nat rule 5010 type masquerade 54 | {% endif %} 55 | 56 | set port-forward auto-firewall {{ "enable" if config.pppoe_interface.auto_firewall else "disable" }} 57 | set port-forward hairpin-nat {{ "enable" if config.pppoe_interface.hairpin_nat else "disable" }} 58 | set port-forward lan-interface {{ "switch0" if config.networks[0].interfaces|length > 1 else config.networks[0].interfaces[0] }} 59 | set port-forward wan-interface pppoe0 60 | 61 | {% for rule in config.port_forwards %} 62 | set port-forward rule {{ loop.index }} description {{ rule.description }} 63 | set port-forward rule {{ loop.index }} forward-to address {{ rule.to_addr }} 64 | set port-forward rule {{ loop.index }} forward-to port {{ rule.to_port }} 65 | set port-forward rule {{ loop.index }} original-port {{ rule.public_port }} 66 | set port-forward rule {{ loop.index }} protocol {{ rule.protocol }} 67 | {% endfor %} 68 | 69 | {% endif %} 70 | 71 | set interfaces loopback lo 72 | 73 | # ==== BEGIN LAN NETWORK CONFIGURATION ==== # 74 | {% for network in config.networks %} 75 | {% set outer_loop = loop %} 76 | 77 | # -- LAN interfaces -- # 78 | {% for interface in network.interfaces %} 79 | set interfaces ethernet {{ interface }} description Local 80 | set interfaces ethernet {{ interface }} duplex auto 81 | set interfaces ethernet {{ interface }} speed auto 82 | {% endfor %} 83 | 84 | {% if network.interfaces|length > 1 %} 85 | # -- Set up switching for LAN interfaces -- # (ER-X only) 86 | set interfaces switch switch{{ outer_loop.index0 }} address {{ network.router_addr }} 87 | set interfaces switch switch{{ outer_loop.index0 }} description "Switch for {{ network.name }}" 88 | set interfaces switch switch{{ outer_loop.index0 }} mtu {{ network.mtu }} 89 | set interfaces switch switch{{ outer_loop.index0 }} switch-port vlan-aware {{ "enable" if network.vlans_enabled else "disable" }} 90 | {% endif %} 91 | 92 | {% if network.interfaces|length > 1 %} 93 | {% for interface in network.interfaces %} 94 | set interfaces switch switch{{ outer_loop.index0 }} switch-port interface {{ interface }} 95 | {% endfor %} 96 | {% endif %} 97 | 98 | # ==== Configure DHCP and DNS ==== # 99 | 100 | # -- Network-specific options -- # 101 | set service dhcp-server shared-network-name {{ network.name }} authoritative enable 102 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} default-router {{ network.dhcp.def_gateway }} 103 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} dns-server {{ network.dhcp.nameserver }} 104 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} lease {{ network.dhcp.lease_ttl }} 105 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} start {{ network.dhcp.start }} stop {{ network.dhcp.end }} 106 | 107 | # -- Static leases for network -- # 108 | {% for lease in network.dhcp_static_leases %} 109 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} static-mapping {{ lease.name }} ip-address {{ lease.ip_addr }} 110 | set service dhcp-server shared-network-name {{ network.name }} subnet {{ network.cidr_block }} static-mapping {{ lease.name }} mac-address '{{ lease.mac_addr }}' 111 | {% endfor %} 112 | 113 | # -- DNS forwarder enable/disable -- # 114 | set service dns forwarding listen-on {{ "switch"+outer_loop.index0|string if network.interfaces|length > 1 else network.interfaces[0] }} 115 | 116 | {% endfor %} 117 | # ==== END NETWORK CONFIGURATION ==== # 118 | 119 | # ==== Complete generic DNS/DHCP setup options ==== # 120 | # -- Global DNS options -- # 121 | set service dhcp-server disabled false 122 | set service dhcp-server hostfile-update disable 123 | set service dhcp-server static-arp disable 124 | set service dhcp-server use-dnsmasq disable 125 | 126 | {% if config.dynamic_dns is defined %} 127 | # -- Dynamic DNS -- # 128 | set service dns dynamic interface {{ config.dynamic_dns.interface }} service {{ config.dynamic_dns.service_type }} host-name {{ config.dynamic_dns.hostname }} 129 | set service dns dynamic interface {{ config.dynamic_dns.interface }} service {{ config.dynamic_dns.service_type }} login {{ config.dynamic_dns.login }} 130 | set service dns dynamic interface {{ config.dynamic_dns.interface }} service {{ config.dynamic_dns.service_type }} password {{ config.dynamic_dns.password }} 131 | set service dns dynamic interface {{ config.dynamic_dns.interface }} service {{ config.dynamic_dns.service_type }} protocol {{ config.dynamic_dns.protocol }} 132 | {% endif %} 133 | 134 | # ==== User accounts ==== # 135 | {% for user in config.users %} 136 | set system login user {{ user.username }} authentication encrypted-password {{ user.encrypted_password }} 137 | set system login user {{ user.username }} authentication plaintext-password {{ user.plaintext_password }} 138 | set system login user {{ user.username }} full-name {{ user.full_name }} 139 | set system login user {{ user.username }} level {{ user.level }} 140 | {% endfor %} 141 | 142 | # ==== NTP configuration ==== # 143 | {% for server in config.ntp %} 144 | set system ntp server {{ server }} 145 | {% endfor %} 146 | 147 | # ==== Other System-Wide Settings ==== # 148 | set service ssh port {{ config.ssh.port }} 149 | set service ssh protocol-version {{ config.ssh.version }} 150 | set service unms {{ "enable" if config.unms_mgmt_enabled else "disable" }} 151 | set service gui http-port {{ config.gui.http_port }} 152 | set service gui https-port {{ config.gui.https_port }} 153 | set service gui older-ciphers {{ "enable" if config.gui.weak_cipher_support else "disable" }} 154 | set service dns forwarding cache-size {{ config.dns_forwarder.cache_size }} 155 | set system host-name {{ config.hostname }} 156 | set system offload hwnat {{ config.offloading.hwnat }} 157 | set system offload ipsec {{ config.offloading.ipsec }} 158 | set system syslog global facility all level notice 159 | set system syslog global facility protocols level debug 160 | set system time-zone {{ config.time_zone }} 161 | --------------------------------------------------------------------------------