SSH Sshuttle: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
(не показано 19 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
[[Категория:Linux]] |
[[Категория:Linux]] |
||
− | [[Категория: |
+ | [[Категория:SSH]] |
+ | [[Категория:sshuttle]] |
||
+ | [[Категория:MacOS X]] |
||
=Shuttle= |
=Shuttle= |
||
Заметка что бы не забыть что да как |
Заметка что бы не забыть что да как |
||
Строка 25: | Строка 27: | ||
Теперь о том, как работает. |
Теперь о том, как работает. |
||
− | + | # в момент запуска sshuttle копирует на удаленный сервер некий assembler.py (/usr/lib/sshuttle/assembler.py с ноута) |
|
− | + | # запускает assembler.py на удаленном сервере (python2 -c import sys; skip_imports=1; verbosity=2; exec compile(sys.stdin.read(764), «assembler.py», «exec»)) |
|
− | + | # запускает на локалхосте /usr/lib/sshuttle/main.py |
|
− | + | # в iptables (в линкус) добавляет правило, по которым весь tcp трафик заворачивается в ssh-туннель. |
|
==DNS трафик через туннель тоже == |
==DNS трафик через туннель тоже == |
||
Строка 51: | Строка 53: | ||
Да, ещё где-то в недрах «это ж опенсорс!» есть версия, которая умеет роутить вообще весь трафик (и icmp, и весь udp), но она не очень похожа на стабильную. |
Да, ещё где-то в недрах «это ж опенсорс!» есть версия, которая умеет роутить вообще весь трафик (и icmp, и весь udp), но она не очень похожа на стабильную. |
||
https://github.com/brianmay/sshuttle/tree/tproxy — вот здесь (это НЕ апстрим проекта). |
https://github.com/brianmay/sshuttle/tree/tproxy — вот здесь (это НЕ апстрим проекта). |
||
+ | |||
+ | ==ssh-cmd== |
||
+ | Можно например так - проброс через несколько хостов |
||
+ | <PRE> |
||
+ | sshuttle -r user@10.245.56.195 10.236.0.0/14 -vv --dns --ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv" |
||
+ | </PRE> |
||
+ | Тут фокус в том что |
||
+ | * За счет строки конфига <code>ProxyJump citadel.some-domin.tld,osbastion.some-domin.tld</code> подключение к хосту <code>10.245.56.195</code> будет идти через два джамп-хоста, после чего сеть 10.236.0.0/14 будет доступна уже через это соединение |
||
+ | * подключение к '''osbastion.some-domin.tld''' происходит через ''' ProxyJump citadel.some-domin.tld''' |
||
+ | <PRE> |
||
+ | |||
+ | Host *some-domin.tld |
||
+ | User mmazur2 |
||
+ | ForwardAgent yes |
||
+ | |||
+ | Host osbastion.some-domin.tld |
||
+ | Hostname 10.252.13.102 |
||
+ | ProxyJump citadel.some-domin.tld |
||
+ | ServerAliveInterval 3600 |
||
+ | DynamicForward 127.0.0.1:6666 |
||
+ | |||
+ | Host ssh.some-domin.tld |
||
+ | Hostname 10.252.12.6 |
||
+ | |||
+ | Host 10.245.56.* 10.245.57.* 10.245.58.* 10.245.59.* 10.245.60.* 10.34.187.* |
||
+ | ForwardAgent yes |
||
+ | ProxyJump citadel.some-domin.tld,osbastion.some-domin.tld |
||
+ | StrictHostKeyChecking no |
||
+ | User mcc-user |
||
+ | IdentitiesOnly yes |
||
+ | IdentityFile ~/path/to/ssh.key |
||
+ | UserKnownHostsFile /dev/null |
||
+ | PasswordAuthentication no |
||
+ | GSSAPIAuthentication no |
||
+ | UserKnownHostsFile=/dev/null |
||
+ | </PRE> |
||
+ | =Как заворачивается трафик= |
||
+ | Никакой (почти) магии - создаются правила файрволла. |
||
+ | <BR> |
||
+ | Например комманда <code>sshuttle --remote ubuntu@server.com 172.31.0.0/24 -v</code> |
||
+ | * Заворачивает траффик для сети <code>172.31.0.0/24</code> через сервер <code>server.com</code> |
||
+ | |||
+ | <code>sudo pfctl -a '*' -sr</code> |
||
+ | <BR> |
||
+ | <PRE> |
||
+ | ... пропущено не относящееся к делу ... |
||
+ | anchor "sshuttle6-12300" all { |
||
+ | pass out inet6 proto tcp from any to ::1 flags S/SA keep state |
||
+ | } |
||
+ | anchor "sshuttle-12300" all { |
||
+ | pass out route-to lo0 inet proto tcp from any to 172.31.0.0/24 flags S/SA keep state |
||
+ | pass out inet proto tcp from any to 127.0.0.1 flags S/SA keep state |
||
+ | } |
||
+ | </PRE> |
||
+ | |||
+ | Формат правил такой: |
||
+ | </BR> |
||
+ | <code> |
||
+ | action [direction] [log] [quick] [on interface] [af] [proto protocol] [from src_addr [port src_port]] [to dst_addr [port dst_port]] [state] |
||
+ | </code> |
||
+ | |||
+ | * <code>action</code> <code>pass</code> Действие предпринимаемое к подходящим пакетам, либо pass, либо block. Действие pass будет пропускать пакеты в ядро для дальнейшей обработки, в то время как действие block будет реагировать так – как указано в опции block-policy. Значение по умолчанию которой можно изменить на block drop или block return. |
||
+ | * <code>direction</code> <code>out</code> Направление движения пакета через интерфейс, либо in, либо out. |
||
+ | * <code>log</code> - отсутвует, без логгирования |
||
+ | * <code>quick </code> - отсутвует, отсутвие этой опции означает что дальнейшие правила будут обработаны |
||
+ | * <code>route-to lo0</code> Для этого у правила pass есть опция route-to (Interface [Gateway]). Указывает, куда отправлять трафик, прошедший по этому правилу. ( |
||
+ | * <code>af</code> <code>inet </code> Предположу что AF == Address Family, ip или ipv6 (inet / inet6) |
||
+ | * <code>proto protocol</code> <code>proto tcp</code> |
||
+ | * <code>from src_addr [port src_port]</code> <code>from any</code> "откуда угодно", порт опущен что означает "любой порт" |
||
+ | * <code>to dst_addr [port dst_port]</code> <code>to 172.31.0.0/24 </code> |
||
+ | * <code>state</code> <code>flags S/SA keep state</code> эту часть еще требуется разобрать =( |
||
+ | |||
+ | Другими словами '''это правило перенаправит все запросы к сети <code>172.31.0.0/24</code> на интерфейс <code>lo0</code>''' |
||
+ | <BR> |
||
+ | Это можно увидеть и в tcpdump |
||
+ | <PRE> |
||
+ | tcpdump -n -i lo0 net 172.31.0.0/24 |
||
+ | tcpdump: verbose output suppressed, use -v[v]... for full protocol decode |
||
+ | listening on lo0, link-type NULL (BSD loopback), snapshot length 524288 bytes |
||
+ | 12:08:04.428549 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [S], seq 3407022323, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 4205579304 ecr 0,sackOK,eol], length 0 |
||
+ | 12:08:04.428669 IP 172.31.0.2.23 > 192.168.22.108.49266: Flags [S.], seq 2560426142, ack 3407022324, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 892227988 ecr 4205579304,sackOK,eol], length 0 |
||
+ | 12:08:04.428681 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [.], ack 1, win 2058, options [nop,nop,TS val 4205579304 ecr 892227988], length 0 |
||
+ | 12:08:04.428691 IP 172.31.0.2.23 > 192.168.22.108.49266: Flags [.], ack 1, win 2058, options [nop,nop,TS val 892227988 ecr 4205579304], length 0 |
||
+ | 12:08:04.429255 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [P.], seq 1:31, ack 1, win 2058, options [nop,nop,TS val 4205579304 ecr 892227988], length 30 [telnet WILL AUTHENTICATION, DO SUPPRESS GO AHEAD, WILL TERMINAL TYPE, WILL NAWS, WILL TSPEED, WILL LFLOW, WILL LINEMODE, WILL NEW-ENVIRON, DO STATUS, WILL XDISPLOC] |
||
+ | </PRE> |
||
+ | |||
+ | |||
+ | Кроме того при старте создается правило (я не знаю как на маке его увидеть) - которое по сути перенаправит все пакеты приложению которое слушает порт 12300 |
||
+ | <PRE> |
||
+ | fw: rules: |
||
+ | rdr pass on lo0 inet proto tcp from ! 127.0.0.1 to 172.31.0.0/24 -> 127.0.0.1 port 12300 |
||
+ | </PRE> |
||
+ | |||
+ | Этот порт слушает сам шаттл |
||
+ | <PRE> |
||
+ | sudo lsof -iTCP -sTCP:LISTEN -n -P | grep 12300 |
||
+ | Python 77498 mmazur 6u IPv6 0x1be787ce0424577d 0t0 TCP [::1]:12300 (LISTEN) |
||
+ | Python 77498 mmazur 8u IPv4 0x1be787c920fe1b85 0t0 TCP 127.0.0.1:12300 (LISTEN) |
||
+ | </PRE> |
||
+ | Далее (насколько я могу судить, тут полной уверенности нет) - передает пакет поверх ssh питону, который запущен на "том конце" |
||
+ | <BR> |
||
+ | '''КАК ИМЕННО происходит передача от локально к удаленному коду на пайтоне мне пока не ясно!''' |
||
+ | |||
+ | =Если что то-то мешает= |
||
+ | Некоторые особо задроченные корпоративные VPNs лезут своими грязными лапками куда не надо (привет, сраный <code>Cato VPN</code>) и могут блокировать работу sshuttle |
||
+ | <BR> |
||
+ | Это можно заметить запустив <code>--ssh-cmd</code> с <code>-vv</code> - активности на консоли не будет |
||
+ | <BR> |
||
+ | Что бы этого избежать надо завернуть трафик мимо тунельного интерфейса, тогда впн теряет к нему интерес но при этом трафик продолжает перехватываться sshuttle и заворачтиваться в ssh |
||
+ | <BR> |
||
+ | <code>utun3</code> - это тунельный интерфейс |
||
+ | <PRE> |
||
+ | ip ro |
||
+ | default via 192.168.22.254 dev en0 |
||
+ | default via utun3 dev utun3 |
||
+ | ... |
||
+ | </PRE> |
||
+ | <code>ip ro add <адрес который должен ходить через sshuttle> via 192.168.22.254</code> (для мака нужен пакет iproute или использовать нативные комманды) |
||
+ | |||
+ | =Ссылки= |
||
+ | * https://debian.pro/1747 |
||
+ | * https://github.com/sshuttle/sshuttle/issues/563 |
Текущая версия на 14:44, 10 сентября 2024
Shuttle
Заметка что бы не забыть что да как
Пример:
sshuttle --remote mcc-user@10.238.27.69 10.238.56.0/24 -vv --dns --ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv"
--remote mcc-user@10.238.27.69
- через какой хост завернуть трафик (туда и только туда нужен доступ по логину/ключу/2FA )10.238.56.0/24
- какую сеть маршрутизировать (в случае МакОС - добавлю подробности!)-vv
- подробный вывод--dns
- в том числе использовать для DNS--ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv"
- как и с какими параметрами подключаться к хосту10.238.27.69
Работает только для tcp/udp/icmp
Еще примеры
Весь трафик
Например для работы в небезхопастных сетях
sshuttle -r user@remoteserver 0.0.0.0/0 -vv
Теперь о том, как работает.
- в момент запуска sshuttle копирует на удаленный сервер некий assembler.py (/usr/lib/sshuttle/assembler.py с ноута)
- запускает assembler.py на удаленном сервере (python2 -c import sys; skip_imports=1; verbosity=2; exec compile(sys.stdin.read(764), «assembler.py», «exec»))
- запускает на локалхосте /usr/lib/sshuttle/main.py
- в iptables (в линкус) добавляет правило, по которым весь tcp трафик заворачивается в ssh-туннель.
DNS трафик через туннель тоже
# sshuttle -r user@remoteserver 0.0.0.0/0 -vv --dns
(учтите, что если у вас в resolv.conf прописаны провайдерские dns-резолверы, то к ним вас после этой команды могут «не пустить». Впрочем — кто такой херней страдает и оставляет провайдерские dns?)
Используем ssh-ключ для коннекта
# sshuttle -r user@remoteserver 0.0.0.0/0 -vv --dns --ssh-cmd "ssh -i /home/username/.ssh/id_dsa"
Используем ssh-агента для коннекта
# sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" sshuttle -r root@messer.qs.biz 0.0.0.0/0 -vv
Отроутим трафик через ssh только до определенных сетей/хостов
# SSH_AUTH_SOCK="$SSH_AUTH_SOCK" sshuttle -r root@remotehost.tld 188.40.35.183/32 153.121.72.212/32 153.121.72.211/32 173.194.122.0/24 -vv
Да, ещё где-то в недрах «это ж опенсорс!» есть версия, которая умеет роутить вообще весь трафик (и icmp, и весь udp), но она не очень похожа на стабильную. https://github.com/brianmay/sshuttle/tree/tproxy — вот здесь (это НЕ апстрим проекта).
ssh-cmd
Можно например так - проброс через несколько хостов
sshuttle -r user@10.245.56.195 10.236.0.0/14 -vv --dns --ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv"
Тут фокус в том что
- За счет строки конфига
ProxyJump citadel.some-domin.tld,osbastion.some-domin.tld
подключение к хосту10.245.56.195
будет идти через два джамп-хоста, после чего сеть 10.236.0.0/14 будет доступна уже через это соединение - подключение к osbastion.some-domin.tld происходит через ProxyJump citadel.some-domin.tld
Host *some-domin.tld User mmazur2 ForwardAgent yes Host osbastion.some-domin.tld Hostname 10.252.13.102 ProxyJump citadel.some-domin.tld ServerAliveInterval 3600 DynamicForward 127.0.0.1:6666 Host ssh.some-domin.tld Hostname 10.252.12.6 Host 10.245.56.* 10.245.57.* 10.245.58.* 10.245.59.* 10.245.60.* 10.34.187.* ForwardAgent yes ProxyJump citadel.some-domin.tld,osbastion.some-domin.tld StrictHostKeyChecking no User mcc-user IdentitiesOnly yes IdentityFile ~/path/to/ssh.key UserKnownHostsFile /dev/null PasswordAuthentication no GSSAPIAuthentication no UserKnownHostsFile=/dev/null
Как заворачивается трафик
Никакой (почти) магии - создаются правила файрволла.
Например комманда sshuttle --remote ubuntu@server.com 172.31.0.0/24 -v
- Заворачивает траффик для сети
172.31.0.0/24
через серверserver.com
sudo pfctl -a '*' -sr
... пропущено не относящееся к делу ... anchor "sshuttle6-12300" all { pass out inet6 proto tcp from any to ::1 flags S/SA keep state } anchor "sshuttle-12300" all { pass out route-to lo0 inet proto tcp from any to 172.31.0.0/24 flags S/SA keep state pass out inet proto tcp from any to 127.0.0.1 flags S/SA keep state }
Формат правил такой:
action [direction] [log] [quick] [on interface] [af] [proto protocol] [from src_addr [port src_port]] [to dst_addr [port dst_port]] [state]
action
pass
Действие предпринимаемое к подходящим пакетам, либо pass, либо block. Действие pass будет пропускать пакеты в ядро для дальнейшей обработки, в то время как действие block будет реагировать так – как указано в опции block-policy. Значение по умолчанию которой можно изменить на block drop или block return.direction
out
Направление движения пакета через интерфейс, либо in, либо out.log
- отсутвует, без логгированияquick
- отсутвует, отсутвие этой опции означает что дальнейшие правила будут обработаныroute-to lo0
Для этого у правила pass есть опция route-to (Interface [Gateway]). Указывает, куда отправлять трафик, прошедший по этому правилу. (af
inet
Предположу что AF == Address Family, ip или ipv6 (inet / inet6)proto protocol
proto tcp
from src_addr [port src_port]
from any
"откуда угодно", порт опущен что означает "любой порт"to dst_addr [port dst_port]
to 172.31.0.0/24
state
flags S/SA keep state
эту часть еще требуется разобрать =(
Другими словами это правило перенаправит все запросы к сети 172.31.0.0/24
на интерфейс lo0
Это можно увидеть и в tcpdump
tcpdump -n -i lo0 net 172.31.0.0/24 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo0, link-type NULL (BSD loopback), snapshot length 524288 bytes 12:08:04.428549 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [S], seq 3407022323, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 4205579304 ecr 0,sackOK,eol], length 0 12:08:04.428669 IP 172.31.0.2.23 > 192.168.22.108.49266: Flags [S.], seq 2560426142, ack 3407022324, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 892227988 ecr 4205579304,sackOK,eol], length 0 12:08:04.428681 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [.], ack 1, win 2058, options [nop,nop,TS val 4205579304 ecr 892227988], length 0 12:08:04.428691 IP 172.31.0.2.23 > 192.168.22.108.49266: Flags [.], ack 1, win 2058, options [nop,nop,TS val 892227988 ecr 4205579304], length 0 12:08:04.429255 IP 192.168.22.108.49266 > 172.31.0.2.23: Flags [P.], seq 1:31, ack 1, win 2058, options [nop,nop,TS val 4205579304 ecr 892227988], length 30 [telnet WILL AUTHENTICATION, DO SUPPRESS GO AHEAD, WILL TERMINAL TYPE, WILL NAWS, WILL TSPEED, WILL LFLOW, WILL LINEMODE, WILL NEW-ENVIRON, DO STATUS, WILL XDISPLOC]
Кроме того при старте создается правило (я не знаю как на маке его увидеть) - которое по сути перенаправит все пакеты приложению которое слушает порт 12300
fw: rules: rdr pass on lo0 inet proto tcp from ! 127.0.0.1 to 172.31.0.0/24 -> 127.0.0.1 port 12300
Этот порт слушает сам шаттл
sudo lsof -iTCP -sTCP:LISTEN -n -P | grep 12300 Python 77498 mmazur 6u IPv6 0x1be787ce0424577d 0t0 TCP [::1]:12300 (LISTEN) Python 77498 mmazur 8u IPv4 0x1be787c920fe1b85 0t0 TCP 127.0.0.1:12300 (LISTEN)
Далее (насколько я могу судить, тут полной уверенности нет) - передает пакет поверх ssh питону, который запущен на "том конце"
КАК ИМЕННО происходит передача от локально к удаленному коду на пайтоне мне пока не ясно!
Если что то-то мешает
Некоторые особо задроченные корпоративные VPNs лезут своими грязными лапками куда не надо (привет, сраный Cato VPN
) и могут блокировать работу sshuttle
Это можно заметить запустив --ssh-cmd
с -vv
- активности на консоли не будет
Что бы этого избежать надо завернуть трафик мимо тунельного интерфейса, тогда впн теряет к нему интерес но при этом трафик продолжает перехватываться sshuttle и заворачтиваться в ssh
utun3
- это тунельный интерфейс
ip ro default via 192.168.22.254 dev en0 default via utun3 dev utun3 ...
ip ro add <адрес который должен ходить через sshuttle> via 192.168.22.254
(для мака нужен пакет iproute или использовать нативные комманды)