From 149a69d85a68568a8cc7e0565fa759ce46b8aac7 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Sat, 22 Apr 2023 00:00:00 +0700 Subject: [PATCH] networking: add IPv6 stable privacy address Also move 'iwd' service to runlevel 'default', so that sysctl settings are applied correctly before it starts. --- filter_plugins/sysconfig_filters.py | 17 +++++++++++++++-- group_vars/all.yml | 4 ++++ roles/essential/tasks/main.yml | 1 - roles/networking/tasks/iwd.yml | 2 +- roles/networking/tasks/main.yml | 22 ++++++++++++++-------- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/filter_plugins/sysconfig_filters.py b/filter_plugins/sysconfig_filters.py index 409331e..87ea3a2 100644 --- a/filter_plugins/sysconfig_filters.py +++ b/filter_plugins/sysconfig_filters.py @@ -1,5 +1,5 @@ from ansible.errors import AnsibleFilterTypeError -from ansible.module_utils.six import string_types +from ansible.module_utils.six import string_types, integer_types # Ansible's "quote" filter is only applied to shell module @@ -28,8 +28,21 @@ def quote_double(str): raise AnsibleFilterTypeError( "|quote_double expects string, got %s instead." % type(str)) +def random_hex(num): + """ + Generate a random hex number within the range [0, num) + + Example: random_hex(2**16 - 1) = 446c + """ + if isinstance(num, integer_types): + import random + return '{:x}'.format(random.randint(0, num)) + else: + raise AnsibleFilterTypeError( + "|random_hex expects integer, got %s instead." % type(num)) + class FilterModule(object): """Custom Ansible jinja2 filters for sysconfig playbook.""" def filters(self): - return {'quote_single': quote_single, 'quote_double': quote_double} + return {'quote_single': quote_single, 'quote_double': quote_double, 'random_hex': random_hex} diff --git a/group_vars/all.yml b/group_vars/all.yml index 497dda8..b4cf170 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -111,6 +111,10 @@ libvirt_daemons: # Whether to use `iwd` or `eiwd` iwd_without_dbus: false +# RFC 7217: generate a stable IPv6 link-local address for SLAAC +# NOTE: this is the default for dhcpcd (slaac private), and `stable-privacy` flag doesn't appear in `ip a` in this case +ipv6_stable_privacy_addr: true + # Public facing network interfaces to configured # - ip4_addr, ip6_addr should include netmask (e.g. 192.168.1.10/24) # - don't include wireless interfaces here as they should use dhcp with iwctl diff --git a/roles/essential/tasks/main.yml b/roles/essential/tasks/main.yml index c96f208..74d26ed 100644 --- a/roles/essential/tasks/main.yml +++ b/roles/essential/tasks/main.yml @@ -77,7 +77,6 @@ name: kernel.core_pattern value: /var/tmp/core-%e.%p.%h.%t state: present - reload: false - name: essential | Change the tty font to {{ console_font }} lineinfile: diff --git a/roles/networking/tasks/iwd.yml b/roles/networking/tasks/iwd.yml index 0fa94aa..ed7938a 100644 --- a/roles/networking/tasks/iwd.yml +++ b/roles/networking/tasks/iwd.yml @@ -27,5 +27,5 @@ iwd_service: '{{ iwd_without_dbus | ternary("eiwd", "iwd") }}' service: name: '{{ iwd_service }}' - runlevel: boot + runlevel: default enabled: true diff --git a/roles/networking/tasks/main.yml b/roles/networking/tasks/main.yml index 60d3404..deec86b 100644 --- a/roles/networking/tasks/main.yml +++ b/roles/networking/tasks/main.yml @@ -7,20 +7,26 @@ group: root mode: '644' -# NOTE: These only get applied on next boot -- name: networking | Set privacy extension for IPv6 +# NOTE: already set in /lib/sysctl.d/00-alpine.conf but it doesn't hurt re-apply +- name: networking | Set IPv6 Privacy Extension (RFC 4941) ansible.posix.sysctl: name: '{{ (item | split("=") | map("trim") | list)[0] }}' - value: '{{ (item | split("=") | map("trim") | list)[1] | quote_single }}' + value: '{{ (item | split("=") | map("trim") | list)[1] }}' state: present - reload: false loop: - net.ipv6.conf.all.use_tempaddr = 2 - net.ipv6.conf.default.use_tempaddr = 2 - - net.ipv6.conf.all.temp_prefered_lft = 60 - - net.ipv6.conf.default.temp_prefered_lft = 60 - - net.ipv6.conf.all.temp_valid_lft = 1440 - - net.ipv6.conf.default.temp_valid_lft = 1440 + +- name: networking | Set IPv6 stable privacy address (RFC 7217) + ansible.posix.sysctl: + name: '{{ (item | split("=") | map("trim") | list)[0] }}' + value: '{{ (item | split("=") | map("trim") | list)[1] }}' + state: present + loop: + - net.ipv6.conf.default.addr_gen_mode = 2 + - net.ipv6.conf.all.addr_gen_mode = 2 + - net.ipv6.conf.default.stable_secret = {{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }}:{{ (2**16 - 1) | random_hex }} # noqa: yaml[line-length] + when: ipv6_stable_privacy_addr | bool - name: networking | Install {{ dhcp_client }} community.general.apk: