aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorheqnx <root@heqnx.com>2025-05-26 15:15:04 +0300
committerheqnx <root@heqnx.com>2025-05-26 15:15:04 +0300
commit8dbd2c0d50390f559934fbec9d2766cf7b5dece0 (patch)
tree18c5bbad27d7ca54c544916a2e3ee770de1eaace
parentfb8a5cdf9e289457aba7967d1bafcadc1d60f9bd (diff)
downloadansible-playbooks-8dbd2c0d50390f559934fbec9d2766cf7b5dece0.tar.gz
ansible-playbooks-8dbd2c0d50390f559934fbec9d2766cf7b5dece0.zip
added setup for ssh hidden service
-rw-r--r--inventory.yaml.example28
-rw-r--r--roles/tor/tasks/main.yaml2
-rw-r--r--roles/tor/tasks/ssh_hidden_service.yaml159
-rw-r--r--roles/tor/tasks/tor_install.yaml1
4 files changed, 179 insertions, 11 deletions
diff --git a/inventory.yaml.example b/inventory.yaml.example
index 9097f34..17282a9 100644
--- a/inventory.yaml.example
+++ b/inventory.yaml.example
@@ -16,21 +16,27 @@ all:
# set this for the ssh-port-fwd-user role
# port_fwd_user: proxyuser
+ # set this to true to enable ssh hidden service for the roles/tor role
+ # enable_ssh_hidden_service: false
+
#server02:
- # ansible_host: 10.11.12.14
- # ansible_user: root
- # ansible_ssh_private_key_file: id_rsa
+ # ansible_host: 10.11.12.14
+ # ansible_user: root
+ # ansible_ssh_private_key_file: id_rsa
- # set this for the sliver-c2 role
- # sliver_server: 127.0.0.1
+ # set this for the sliver-c2 role
+ # sliver_server: 127.0.0.1
+
+ # set these for the ssh-nginx-multiplex role
+ # public_sslh_port: 443
+ # internal_nginx_port: 8080
+ # internal_sshd_port: 22
- # set these for the ssh-nginx-multiplex role
- # public_sslh_port: 443
- # internal_nginx_port: 8080
- # internal_sshd_port: 22
+ # set this for the ssh-port-fwd-user role
+ # port_fwd_user: proxyuser
- # set this for the ssh-port-fwd-user role
- # port_fwd_user: proxyuser
+ # set this to true to enable ssh hidden service for the roles/tor role
+ # enable_ssh_hidden_service: false
children:
servers:
diff --git a/roles/tor/tasks/main.yaml b/roles/tor/tasks/main.yaml
index 3168032..d5a05f1 100644
--- a/roles/tor/tasks/main.yaml
+++ b/roles/tor/tasks/main.yaml
@@ -1 +1,3 @@
- import_tasks: tasks/tor_install.yaml
+- import_tasks: tasks/ssh_hidden_service.yaml
+ when: enable_ssh_hidden_service | default(false)
diff --git a/roles/tor/tasks/ssh_hidden_service.yaml b/roles/tor/tasks/ssh_hidden_service.yaml
new file mode 100644
index 0000000..cbac7fa
--- /dev/null
+++ b/roles/tor/tasks/ssh_hidden_service.yaml
@@ -0,0 +1,159 @@
+- name: create directory for ssh hidden service
+ file:
+ path: /var/lib/tor/ssh
+ state: directory
+ owner: debian-tor
+ group: debian-tor
+ mode: '0700'
+
+- name: ensure ssh hidden service is configured in torrc
+ blockinfile:
+ path: /etc/tor/torrc
+ marker: "# {mark} ANSIBLE MANAGED SSH HIDDEN SERVICE"
+ block: |
+ HiddenServiceDir /var/lib/tor/ssh
+ HiddenServicePort 22 127.0.0.1:22
+ notify: restart tor
+
+- name: wait for hidden service hostname file
+ wait_for:
+ path: /var/lib/tor/ssh/hostname
+ timeout: 120
+
+- name: wait for hidden service secret key file
+ wait_for:
+ path: /var/lib/tor/ssh/hs_ed25519_secret_key
+ timeout: 120
+
+- name: read hidden service hostname
+ slurp:
+ src: /var/lib/tor/ssh/hostname
+ register: hs_hostname_raw
+
+- name: set fact with cleaned .onion hostname
+ set_fact:
+ onion_address: "{{ hs_hostname_raw.content | b64decode | trim }}"
+
+- name: ensure ssh key for onion access exists on target
+ openssh_keypair:
+ path: /root/.ssh/id_ed25519_onion
+ type: ed25519
+ owner: root
+ group: root
+ mode: '0600'
+ register: onion_ssh_key
+
+- name: read onion ssh public key from target
+ slurp:
+ src: /root/.ssh/id_ed25519_onion.pub
+ register: onion_ssh_pubkey_raw
+
+- name: add onion ssh public key to authorized_keys
+ authorized_key:
+ user: root
+ state: present
+ key: "{{ onion_ssh_pubkey_raw.content | b64decode }}"
+
+- name: create local directory for ssh config.d
+ file:
+ path: "./{{ onion_address }}/config.d"
+ state: directory
+ mode: '0700'
+ become: false
+ delegate_to: localhost
+ run_once: true
+
+- name: generate modular SSH config file
+ copy:
+ dest: "./{{ onion_address }}/ssh_config"
+ content: |
+ Include config.d/*
+ Host *.onion
+ ProxyCommand nc -x 127.0.0.1:9050 -X 5 %h %p
+ become: false
+ delegate_to: localhost
+ run_once: true
+
+- name: fetch generated onion ssh private key
+ fetch:
+ src: /root/.ssh/id_ed25519_onion
+ dest: "./{{ onion_address }}/{{ onion_address }}_id_ed25519"
+ flat: yes
+
+- name: set correct permissions on fetched hidden service private key
+ file:
+ path: "./{{ onion_address }}/{{ onion_address }}_id_ed25519"
+ mode: '0600'
+ delegate_to: localhost
+
+- name: fetch generated onion ssh public key
+ fetch:
+ src: /root/.ssh/id_ed25519_onion.pub
+ dest: "./{{ onion_address }}/{{ onion_address }}_id_ed25519.pub"
+ flat: yes
+
+- name: fetch hidden service private key
+ fetch:
+ src: "/var/lib/tor/ssh/hs_ed25519_secret_key"
+ dest: "./{{ onion_address }}/hs_ed25519_secret_key"
+ flat: yes
+ mode: '0600'
+
+- name: generate onion-specific ssh config snippet
+ copy:
+ dest: "./{{ onion_address }}/config.d/{{ onion_address }}"
+ content: |
+ Host {{ onion_address }}
+ HostName {{ onion_address }}
+ Port 22
+ User {{ ansible_user | default('root') }}
+ PubkeyAuthentication yes
+ IdentityFile ../{{ onion_address }}_id_ed25519
+ VerifyHostKeyDNS no
+ become: false
+ delegate_to: localhost
+ run_once: true
+
+- name: generate ssh wrapper script
+ copy:
+ dest: "./{{ onion_address }}/ssh_{{ onion_address }}"
+ content: |
+ #!/bin/bash
+
+ SOCKS_PORT=9050
+ SOCKS_HOST=127.0.0.1
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ CONFIG_FILE="$SCRIPT_DIR/ssh_config"
+ KEY_FILE="$SCRIPT_DIR/{{ onion_address }}_id_ed25519"
+ ONION_HOST="{{ onion_address }}"
+ USER="root"
+
+ if ! pgrep -x tor >/dev/null; then
+ printf "%s\n" "[err] tor process is not running"
+ exit 1
+ fi
+
+ if ! nc -z "$SOCKS_HOST" "$SOCKS_PORT"; then
+ printf "%s\n" "[err] tor socks proxy $SOCKS_HOST:$SOCKS_PORT is not reachable"
+ exit 1
+ fi
+
+ if ! test -f "$CONFIG_FILE"; then
+ printf "%s\n" "[err] ssh config not found: $CONFIG_FILE"
+ exit 1
+ fi
+
+ if ! test -f "$KEY_FILE"; then
+ printf "%s\n" "[err] identity file not found: $KEY_FILE"
+ exit 1
+ fi
+
+ exec ssh \
+ -F "$CONFIG_FILE" \
+ -i "$KEY_FILE" \
+ "$USER@$ONION_HOST" \
+ "$@"
+ mode: '0755'
+ become: false
+ delegate_to: localhost
+ run_once: true
diff --git a/roles/tor/tasks/tor_install.yaml b/roles/tor/tasks/tor_install.yaml
index 8b3d725..96cf98e 100644
--- a/roles/tor/tasks/tor_install.yaml
+++ b/roles/tor/tasks/tor_install.yaml
@@ -6,6 +6,7 @@
- torsocks
- proxychains
- curl
+ - netcat-openbsd
state: present
update_cache: true