blob: d2415f2f749e185efc610b43a4efffbd60b8bb82 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
- 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
- name: restart tor
systemd:
name: tor
state: restarted
enabled: true
when: ansible_service_mgr == 'systemd'
- 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: true
- 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: true
- name: fetch hidden service private key
fetch:
src: "/var/lib/tor/ssh/hs_ed25519_secret_key"
dest: "./{{ onion_address }}/hs_ed25519_secret_key"
flat: true
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
|