SSH Sshuttle: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 20 промежуточных версий этого же участника)
Строка 1: Строка 1:
 
[[Категория:Linux]]
 
[[Категория:Linux]]
[[Категория:ssh]]
+
[[Категория:SSH]]
  +
[[Категория:sshuttle]]
  +
[[Категория:MacOS X]]
 
=Shuttle=
 
=Shuttle=
 
Заметка что бы не забыть что да как
 
Заметка что бы не забыть что да как
Строка 13: Строка 15:
 
* <code>--dns</code> - в том числе использовать для DNS
 
* <code>--dns</code> - в том числе использовать для DNS
 
* <code>--ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv"</code> - как и с какими параметрами подключаться к хосту <code>10.238.27.69</code>
 
* <code>--ssh-cmd "ssh -F /Users/mmazur/ssh_config -vv"</code> - как и с какими параметрами подключаться к хосту <code>10.238.27.69</code>
  +
  +
  +
Работает только для tcp/udp/icmp
  +
  +
Еще примеры
  +
==Весь трафик==
  +
Например для работы в небезхопастных сетях
  +
<PRE>
  +
sshuttle -r user@remoteserver 0.0.0.0/0 -vv
  +
</PRE>
  +
  +
Теперь о том, как работает.
  +
# в момент запуска 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 трафик через туннель тоже ==
  +
<PRE>
  +
# sshuttle -r user@remoteserver 0.0.0.0/0 -vv --dns
  +
</PRE>
  +
(учтите, что если у вас в resolv.conf прописаны провайдерские dns-резолверы, то к ним вас после этой команды могут «не пустить». Впрочем — кто такой херней страдает и оставляет провайдерские dns?)
  +
  +
==Используем ssh-ключ для коннекта==
  +
<PRE>
  +
# sshuttle -r user@remoteserver 0.0.0.0/0 -vv --dns --ssh-cmd "ssh -i /home/username/.ssh/id_dsa"
  +
</PRE>
  +
==Используем ssh-агента для коннекта==
  +
<PRE>
  +
# sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" sshuttle -r root@messer.qs.biz 0.0.0.0/0 -vv
  +
</PRE>
  +
==Отроутим трафик через ssh только до определенных сетей/хостов==
  +
<PRE>
  +
# 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
  +
</PRE>
  +
  +
Да, ещё где-то в недрах «это ж опенсорс!» есть версия, которая умеет роутить вообще весь трафик (и icmp, и весь udp), но она не очень похожа на стабильную.
  +
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

Теперь о том, как работает.

  1. в момент запуска sshuttle копирует на удаленный сервер некий assembler.py (/usr/lib/sshuttle/assembler.py с ноута)
  2. запускает assembler.py на удаленном сервере (python2 -c import sys; skip_imports=1; verbosity=2; exec compile(sys.stdin.read(764), «assembler.py», «exec»))
  3. запускает на локалхосте /usr/lib/sshuttle/main.py
  4. в 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 или использовать нативные комманды)

Ссылки