1846
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
ansible.builtin.set_fact:
|
||||
dev2_passfile_used_direct: "NONE"
|
||||
dev2_passfile_used_tunnel: "NONE"
|
||||
dev2_passfile_used_tunnel6: "NONE"
|
||||
dev2_passfile_used_lldp4: "NONE"
|
||||
dev2_passfile_used_lldp6: "NONE"
|
||||
changed_when: false
|
||||
@@ -75,7 +76,6 @@
|
||||
# sleep 10
|
||||
# ignore_errors: true
|
||||
|
||||
|
||||
- name: Discover DEV2 candidate IPv4 via LLDP on DEV1 (best-effort)
|
||||
ansible.builtin.raw: >
|
||||
{{ pathprefix }}
|
||||
@@ -312,12 +312,19 @@
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Stop if tunnel TCP probe failed
|
||||
when: dev2_conn_method == "tunnel" and nc_probe.rc != 0
|
||||
- name: Record IPv4 tunnel probe status
|
||||
when: dev2_conn_method == "tunnel"
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
tunnel_v4_ok: "{{ (nc_probe.rc | default(1)) == 0 }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Stop if tunnel TCP probe failed and no IPv6 candidate exists
|
||||
when: dev2_conn_method == "tunnel" and not (tunnel_v4_ok | bool) and (lldp_dev2_ip6 | default('') | trim | length) == 0
|
||||
ansible.builtin.meta: end_host
|
||||
|
||||
- name: Pick DEV2 password for root (tunnel) try basicpass
|
||||
when: dev2_conn_method == "tunnel"
|
||||
when: dev2_conn_method == "tunnel" and (tunnel_v4_ok | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
@@ -331,14 +338,14 @@
|
||||
ignore_errors: true
|
||||
|
||||
- name: Select basicpass if tunnel login succeeded
|
||||
when: dev2_conn_method == "tunnel" and dev2_try_basicpass.rc == 0
|
||||
when: dev2_conn_method == "tunnel" and (tunnel_v4_ok | bool) and dev2_try_basicpass.rc == 0
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
dev2_passfile_used_tunnel: "basicpass"
|
||||
changed_when: false
|
||||
|
||||
- name: Try DEV2 login through tunnel with basicpass2 (only if first failed)
|
||||
when: dev2_conn_method == "tunnel" and (dev2_passfile_used_tunnel == "NONE")
|
||||
when: dev2_conn_method == "tunnel" and (tunnel_v4_ok | bool) and (dev2_passfile_used_tunnel == "NONE")
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
@@ -352,13 +359,149 @@
|
||||
ignore_errors: true
|
||||
|
||||
- name: Select basicpass2 if tunnel login succeeded
|
||||
when: dev2_conn_method == "tunnel" and dev2_passfile_used_tunnel == "NONE" and dev2_try_basicpass2.rc == 0
|
||||
when: dev2_conn_method == "tunnel" and (tunnel_v4_ok | bool) and dev2_passfile_used_tunnel == "NONE" and dev2_try_basicpass2.rc == 0
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
dev2_passfile_used_tunnel: "basicpass2"
|
||||
changed_when: false
|
||||
|
||||
- name: Decide final DEV2 connection mode (direct_lldp > tunnel > lldp4 > lldp6)
|
||||
- name: Record need for IPv6 tunnel attempt
|
||||
when: dev2_conn_method == "tunnel"
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
need_tunnel6: >-
|
||||
{{
|
||||
(
|
||||
(not (tunnel_v4_ok | default(false) | bool))
|
||||
or
|
||||
((dev2_passfile_used_tunnel | default('NONE')) == 'NONE')
|
||||
)
|
||||
and
|
||||
((lldp_dev2_ip6 | default('') | trim | length) > 0)
|
||||
}}
|
||||
changed_when: false
|
||||
|
||||
- name: Pick a free local TCP port for the IPv6 tunnel (controller side)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
pick() {
|
||||
for i in $(seq 1 25); do
|
||||
p="$(shuf -i 20000-39999 -n 1)"
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
if ! ss -ltn | awk '{print $4}' | grep -qE "(:|\.)${p}$"; then
|
||||
echo "$p"; return 0
|
||||
fi
|
||||
else
|
||||
if ! nc -z 127.0.0.1 "$p" >/dev/null 2>&1; then
|
||||
echo "$p"; return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
pick
|
||||
args: { executable: /bin/bash }
|
||||
register: pick_port6
|
||||
changed_when: false
|
||||
|
||||
- name: Stop if no free local port was found for IPv6 tunnel
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool) and (pick_port6.stdout | trim | length) == 0
|
||||
ansible.builtin.meta: end_host
|
||||
|
||||
- name: Create control dir for SSH ControlMaster (IPv6 tunnel)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: "mktemp -d"
|
||||
args: { executable: /bin/bash }
|
||||
register: mktemp_dir6
|
||||
changed_when: false
|
||||
|
||||
- name: Record chosen local port and build ControlMaster socket path (IPv6 tunnel)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
_local_port6: "{{ pick_port6.stdout | trim }}"
|
||||
_ctrl_dir6: "{{ mktemp_dir6.stdout | trim }}"
|
||||
_ctrl_sock6: "{{ (mktemp_dir6.stdout | trim) }}/ssh_tunnel_ctl6"
|
||||
changed_when: false
|
||||
|
||||
- name: Start SSH ControlMaster and forward 127.0.0.1:local_port6 to DEV2 22 via DEV1 (IPv6)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
USER="{{ dev1_user }}"
|
||||
HOST="{{ ansible_host | default(inventory_hostname) }}"
|
||||
IP6="{{ lldp_dev2_ip6 | trim }}"
|
||||
sshpass -p '{{ dev1_pass }}' ssh -f -N {{ ssh_opts_common }} \
|
||||
-M -S "{{ _ctrl_sock6 }}" \
|
||||
-L "127.0.0.1:{{ _local_port6 }}:[${IP6}%{{ dev1_iface }}]:{{ dev2_port }}" \
|
||||
"${USER}@${HOST}"
|
||||
args: { executable: /bin/bash }
|
||||
register: start_tunnel6
|
||||
changed_when: true
|
||||
ignore_errors: true
|
||||
|
||||
- name: Probe TCP reachability to DEV2 through the IPv6 tunnel (nc)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
nc -z -w5 127.0.0.1 "{{ _local_port6 }}"
|
||||
args: { executable: /bin/bash }
|
||||
register: nc_probe6
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Stop if IPv6 tunnel TCP probe failed
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool) and (nc_probe6.rc | default(1)) != 0
|
||||
ansible.builtin.meta: end_host
|
||||
|
||||
- name: Pick DEV2 password for root (IPv6 tunnel) try basicpass
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
PORT="{{ _local_port6 }}"
|
||||
sshpass -f basicpass ssh {{ ssh_opts_common }} \
|
||||
-o AddressFamily=inet \
|
||||
-p "$PORT" root@127.0.0.1 echo OK >/dev/null 2>&1
|
||||
args: { executable: /bin/bash }
|
||||
register: dev2_try_basicpass6
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Select basicpass if IPv6 tunnel login succeeded
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool) and dev2_try_basicpass6.rc == 0
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
dev2_passfile_used_tunnel6: "basicpass"
|
||||
changed_when: false
|
||||
|
||||
- name: Try DEV2 login through IPv6 tunnel with basicpass2 (only if first failed)
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool) and (dev2_passfile_used_tunnel6 == "NONE")
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
set -e
|
||||
PORT="{{ _local_port6 }}"
|
||||
sshpass -f basicpass2 ssh {{ ssh_opts_common }} \
|
||||
-o AddressFamily=inet \
|
||||
-p "$PORT" root@127.0.0.1 echo OK >/dev/null 2>&1
|
||||
args: { executable: /bin/bash }
|
||||
register: dev2_try_basicpass26
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Select basicpass2 if IPv6 tunnel login succeeded
|
||||
when: dev2_conn_method == "tunnel" and (need_tunnel6 | bool) and dev2_passfile_used_tunnel6 == "NONE" and dev2_try_basicpass26.rc == 0
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
dev2_passfile_used_tunnel6: "basicpass2"
|
||||
changed_when: false
|
||||
|
||||
- name: Decide final DEV2 connection mode (direct_lldp > tunnel > tunnel6 > lldp4 > lldp6)
|
||||
delegate_to: localhost
|
||||
ansible.builtin.set_fact:
|
||||
dev2_conn_final: >-
|
||||
@@ -366,6 +509,8 @@
|
||||
direct_lldp
|
||||
{%- elif dev2_conn_method == 'tunnel' and (dev2_passfile_used_tunnel | default('NONE')) != 'NONE' -%}
|
||||
tunnel
|
||||
{%- elif dev2_conn_method == 'tunnel' and (dev2_passfile_used_tunnel6 | default('NONE')) != 'NONE' -%}
|
||||
tunnel6
|
||||
{%- else -%}
|
||||
none
|
||||
{%- endif -%}
|
||||
@@ -377,6 +522,7 @@
|
||||
msg: >
|
||||
DEV2 unreachable:
|
||||
tunnel={{ dev2_passfile_used_tunnel | default('n/a') }},
|
||||
tunnel6={{ dev2_passfile_used_tunnel6 | default('n/a') }},
|
||||
direct={{ dev2_passfile_used_direct | default('n/a') }}.
|
||||
|
||||
- name: Debug final connectivity decision
|
||||
@@ -386,8 +532,10 @@
|
||||
msg:
|
||||
- "dev2_conn_final={{ dev2_conn_final }}"
|
||||
- "tunnel passfile={{ dev2_passfile_used_tunnel | default('n/a') }}"
|
||||
- "tunnel6 passfile={{ dev2_passfile_used_tunnel6 | default('n/a') }}"
|
||||
- "direct passfile={{ dev2_passfile_used_direct | default('n/a') }}"
|
||||
- "tunnel target={{ dev2_host }}:{{ dev2_port }} forwarded 127.0.0.1:{{ _local_port | default('na') }}"
|
||||
- "tunnel6 target={{ lldp_dev2_ip6 | default('') }}%{{ dev1_iface }}:{{ dev2_port }} forwarded 127.0.0.1:{{ _local_port6 | default('na') }}"
|
||||
- "lldp ipv4={{ lldp_dev2_ip | default('') }}"
|
||||
- "lldp ipv6={{ lldp_dev2_ip6 | default('') }}"
|
||||
|
||||
@@ -411,6 +559,14 @@
|
||||
-p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \
|
||||
"{{ pathprefix }} ${DEV2_CMD}" 2>&1
|
||||
;;
|
||||
tunnel6)
|
||||
PORT="{{ _local_port6 | default('') }}"
|
||||
PASS="{{ dev2_passfile_used_tunnel6 }}"
|
||||
sshpass -f "$PASS" ssh {{ ssh_opts_common }} \
|
||||
-o AddressFamily=inet \
|
||||
-p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \
|
||||
"{{ pathprefix }} ${DEV2_CMD}" 2>&1
|
||||
;;
|
||||
direct_lldp)
|
||||
HOST="{{ lldp_dev2_ip }}"
|
||||
PASS="{{ dev2_passfile_used_direct }}"
|
||||
@@ -730,6 +886,15 @@
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Close SSH ControlMaster (IPv6 tunnel best-effort)
|
||||
when: dev2_conn_method | default('') == "tunnel"
|
||||
delegate_to: localhost
|
||||
ansible.builtin.shell: |
|
||||
ssh -S "{{ _ctrl_sock6 | default('/dev/null') }}" -O exit 2>/dev/null || true
|
||||
args: { executable: /bin/bash }
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove tunnel control dir (best-effort)
|
||||
when: dev2_conn_method | default('') == "tunnel"
|
||||
delegate_to: localhost
|
||||
@@ -738,6 +903,14 @@
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove tunnel control dir (IPv6 tunnel best-effort)
|
||||
when: dev2_conn_method | default('') == "tunnel"
|
||||
delegate_to: localhost
|
||||
ansible.builtin.file:
|
||||
path: "{{ _ctrl_dir6 | default('/tmp/none') }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove staged passfiles from DEV1 (best-effort)
|
||||
when: dev2_conn_method | default('') == "tunnel"
|
||||
ansible.builtin.raw: >
|
||||
|
||||
Reference in New Issue
Block a user