diff --git a/files/ansible-playbooks/update-indoor.yml b/files/ansible-playbooks/update-indoor.yml index b54c0f7..e43da8b 100644 --- a/files/ansible-playbooks/update-indoor.yml +++ b/files/ansible-playbooks/update-indoor.yml @@ -165,6 +165,33 @@ register: pick_port changed_when: false + - name: Debug picked local port (controller) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "picked_local_port={{ _local_port }}" + - "ctrl_sock={{ _ctrl_sock }}" + - "dev1_host={{ ansible_host | default(inventory_hostname) }}" + - "dev2_target={{ dev2_host }}:{{ dev2_port }}" + + - name: Show current listeners on picked port (ss/lsof) + delegate_to: localhost + ansible.builtin.shell: | + set -e + P="{{ _local_port }}" + { ss -ltnp 2>/dev/null || true; } | awk -v p=":${P}$" '$0 ~ p' + { lsof -nP -iTCP:"${P}" -sTCP:LISTEN 2>/dev/null || true; } + register: port_listeners_before + changed_when: false + failed_when: false + + - name: Debug listeners on picked port (before starting tunnel) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "listeners_before:\n{{ (port_listeners_before.stdout | default('')) | trim }}" + + - name: Stop if no free local port was found ansible.builtin.meta: end_host when: (pick_port.stdout | trim | length) == 0 @@ -207,6 +234,36 @@ register: start_tunnel changed_when: true + - name: Debug ControlMaster start result (rc/stdout/stderr) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "start_tunnel.rc={{ start_tunnel.rc | default('NA') }}" + - "start_tunnel.stdout={{ (start_tunnel.stdout | default('')) | trim }}" + - "start_tunnel.stderr={{ (start_tunnel.stderr | default('')) | trim }}" + + - name: Show who is listening now on the local port (post-start) + delegate_to: localhost + ansible.builtin.shell: | + set -e + P="{{ _local_port }}" + echo "== ss -ltnp on :${P} ==" + { ss -ltnp 2>/dev/null || true; } | awk -v p=":${P}$" '$0 ~ p {print}' + echo "== lsof LISTEN on :${P} ==" + { lsof -nP -iTCP:"${P}" -sTCP:LISTEN 2>/dev/null || true; } + echo "== grep ControlMaster PID ==" + pgrep -fa "ssh.*-S {{ _ctrl_sock | regex_escape }}" || true + register: port_listeners_after + changed_when: false + failed_when: false + + - name: Debug listeners on picked port (after starting tunnel) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "{{ (port_listeners_after.stdout | default('')) | trim }}" + + - name: Wait a moment for tunnel to settle delegate_to: localhost ansible.builtin.wait_for: @@ -229,6 +286,15 @@ - "tunnel_check.rc={{ tun_check.rc }}" - "tunnel_check.out={{ (tun_check.stdout | default('')) | trim }}" + # ADD THIS RIGHT AFTER THE EXISTING DEBUG: + - name: Debug ControlMaster check (full rc/stdout/stderr) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "tun_check.rc={{ tun_check.rc | default('NA') }}" + - "tun_check.stdout={{ (tun_check.stdout | default('')) | trim }}" + - "tun_check.stderr={{ (tun_check.stderr | default('')) | trim }}" + # ---------------------------- Controller-side sanity for DEV2 auth ---------------------------- - name: Probe TCP reachability to DEV2 through the tunnel (nc) delegate_to: localhost @@ -266,7 +332,57 @@ - "{{ (dev2_ls.stdout | default('')) | trim }}" - "{{ (dev2_ls.stderr | default('')) | trim }}" + + - name: Probe SSH banner through tunnel without auth (quick) + delegate_to: localhost + ansible.builtin.shell: | + set -e + PORT="{{ _local_port }}" + # No password, no interactive auth; prints preauth/banners then exits + ssh -p "$PORT" \ + -o PreferredAuthentications=none \ + -o PubkeyAuthentication=no \ + -o KbdInteractiveAuthentication=no \ + -o PasswordAuthentication=no \ + -o NumberOfPasswordPrompts=0 \ + -o ConnectTimeout=5 \ + -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -vvv root@127.0.0.1 true 2>&1 || true + register: tunnel_banner_probe + changed_when: false + failed_when: false + + - name: Debug SSH preauth probe output (first 40 lines) + delegate_to: localhost + ansible.builtin.debug: + msg: "{{ (tunnel_banner_probe.stdout | default('')) | regex_replace('^(?:.*\\n){,40}\\K[\\s\\S]*','[...truncated...]') }}" + + # ---------------------------- Pick DEV2 password for root ---------------------------- + - name: Probe SSH banner through tunnel (pre-auth, quick) + delegate_to: localhost + ansible.builtin.shell: | + set -e + PORT="{{ _local_port }}" + ssh -p "$PORT" \ + -o PreferredAuthentications=none \ + -o PubkeyAuthentication=no \ + -o KbdInteractiveAuthentication=no \ + -o PasswordAuthentication=no \ + -o NumberOfPasswordPrompts=0 \ + -o ConnectTimeout=5 \ + -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -vvv root@127.0.0.1 true 2>&1 || true + register: tunnel_banner_probe + changed_when: false + failed_when: false + + - name: Debug SSH preauth probe (first 40 lines) + delegate_to: localhost + ansible.builtin.debug: + msg: "{{ (tunnel_banner_probe.stdout | default('')) | regex_replace('^(?:.*\\n){,40}\\K[\\s\\S]*','[...truncated...]') }}" + + - name: Try DEV2 login with 'basicpass' (root) delegate_to: localhost ansible.builtin.shell: | @@ -282,6 +398,31 @@ changed_when: false ignore_errors: true + - name: Snapshot listeners on local tunnel port (after basicpass try) + delegate_to: localhost + ansible.builtin.shell: | + set -e + P="{{ _local_port }}" + echo "== ss -ltnp on :${P} ==" + { ss -ltnp 2>/dev/null || true; } | awk -v p=":${P}$" '$0 ~ p {print}' + echo "== lsof LISTEN on :${P} ==" + { lsof -nP -iTCP:"${P}" -sTCP:LISTEN 2>/dev/null || true; } + echo "== pgrep ControlMaster by socket ==" + pgrep -fa "ssh.*-S {{ _ctrl_sock | regex_escape }}" || true + register: listeners_after_basicpass + changed_when: false + failed_when: false + + - name: Debug auth try context (basicpass) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "auth_try=basicpass rc={{ dev2_try_basicpass.rc | default('NA') }}" + - "local_port={{ _local_port }}" + - "ctrl_sock={{ _ctrl_sock }}" + - "listeners:\n{{ (listeners_after_basicpass.stdout | default('')) | trim }}" + + - name: Select 'basicpass' if previous login succeeded when: dev2_try_basicpass.rc == 0 delegate_to: localhost @@ -305,6 +446,32 @@ changed_when: false ignore_errors: true + - name: Snapshot listeners on local tunnel port (after basicpass2 try) + delegate_to: localhost + ansible.builtin.shell: | + set -e + P="{{ _local_port }}" + echo "== ss -ltnp on :${P} ==" + { ss -ltnp 2>/dev/null || true; } | awk -v p=":${P}$" '$0 ~ p {print}' + echo "== lsof LISTEN on :${P} ==" + { lsof -nP -iTCP:"${P}" -sTCP:LISTEN 2>/dev/null || true; } + echo "== pgrep ControlMaster by socket ==" + pgrep -fa "ssh.*-S {{ _ctrl_sock | regex_escape }}" || true + register: listeners_after_basicpass2 + changed_when: false + failed_when: false + + - name: Debug auth try context (basicpass2) + delegate_to: localhost + ansible.builtin.debug: + msg: + - "auth_try=basicpass2 rc={{ dev2_try_basicpass2.rc | default('NA') }}" + - "local_port={{ _local_port }}" + - "ctrl_sock={{ _ctrl_sock }}" + - "listeners:\n{{ (listeners_after_basicpass2.stdout | default('')) | trim }}" + when: dev2_try_basicpass2 is defined + + - name: Select 'basicpass2' if second login succeeded when: dev2_passfile_used is not defined and dev2_try_basicpass2.rc == 0 delegate_to: localhost