Получить исходный IP-адрес из обратного туннеля SSH

Отключение IPv6 в системе Linux относительно безопасно , если ваш оператор не предоставляет его ; однако после отключения IPv6 вам может понадобиться возиться с конфигурацией нечетного демона, чья конфигурация предполагает, что он активен (xinetd и postfix приходят на ум ).

Однако вам может не понадобиться отключать IPv6 в вашей системе только для Firefox.

В Firefox есть набор параметров, которые вы можете настроить, чтобы изменить нормальное поведение. :Откройте about:configв Firefox, в поле поиска напишите IPv6и, увидев network.dns.disableIPv6, щелкните два раза на falseзначение, чтобы оно стало true.

После изменения этой переменной больше не будет операций IPv6 в Firefox. Сначала попробуйте это, так как это довольно легко изменить, и измените его обратно.

7
23.04.2019, 14:36
5 ответов

Команда lsof в Linux отображает в выводе информацию о файлах, открытых процессами

Получение идентификатора процесса ssh из netstat,

lsof -p $pid -a -d 3

покажет IP другого конца соединения. Поскольку через ssh можно прыгать, это может быть не окончательное местоположение.

$pid — идентификатор процесса вашего ssh-сервиса

если у вас нет lsof, вы можете установить его с помощьюapt-get install lsof

1
27.01.2020, 20:17

Как уже упоминалось, вам нужно дождаться установления соединения, прежде чем вы сможете увидеть внешний адрес (на удаленной стороне )соединения. Вы можете получить эту информацию двумя способами:

Любой из этих методов выполняется асинхронно, и вам потребуется поддерживать обработку соединения отдельно от ssh.

1
27.01.2020, 20:17

Я не могу дать вам ни одной команды, но есть несколько команд, которые позволят вам найти клиента. Проблема в том, как OpenSSH создает процессы. Процесс, владеющий прослушивающим сокетом 39963, является дочерним по отношению к процессу, владеющему SSH-соединением. Таким образом, у них будут разные PID. В вашем примере вам нужно найти родительский процесс для 1074. Следующее работает для сервера OpenSSH в Ubuntu. Я не могу гарантировать, что каждый дистрибутив будет вести себя одинаково.

Начните с поиска PID для клиентского соединения. Используйте grepдля фильтрации вывода netstat.

$ sudo netstat -ptln | grep 39963
tcp        0      0 127.0.0.1:39963         0.0.0.0:*               LISTEN      21921/sshd: philip@
tcp6       0      0 ::1:39963               :::*                    LISTEN      21921/sshd: philip@

Процесс прослушивания здесь 21921. Вам нужен его родитель:

$ ps -ef | grep 21921
philip   21921 21919  0 11:01 ?        00:00:00 sshd: philip@pts/1
philip   21924 21921  0 11:01 pts/1    00:00:00 -bash
philip   22844 20309  0 11:15 pts/0    00:00:00 grep --color=auto 21921

# Or try this:

$ ps -ef | awk '$2 == 21921 { print $3 }'
21919

Родителем 21921здесь является 21919. Теперь вернемся к netstat, чтобы найти клиента :

.
$ sudo netstat -ptn | grep 21919
tcp        0      0 192.168.1.36:22          192.168.1.10:54425   ESTABLISHED 21919/sshd: philip

Это показывает, что удаленный IP-адрес192.168.1.10

6
27.01.2020, 20:17

Клиент SSH и сервер обмениваются сообщениями для настройки переадресации, но сетевая таблица ядра заботится/знает только о своем локальном стеке IP, поэтому видит только sshd.

Но OpenSSH также использует некоторые детали среды (, которые также передаются через обмен сообщениями ).

 sshcpid=$(pgrep -P 1074)               # fetch child PID
 xargs -0 -L1 -a /proc/$sshcpid/environ # show environment strings

Обе переменные SSH_CLIENTи SSH_CONNECTIONдолжны содержать то, что вам нужно.

Здесь xargs— это удобный способ обработки строк с разделителями NUL вenviron.

Это предполагает:

  • linux, для /procсenviron
  • OpenSSH с такой цепочкой процессов, как:

    демон sshd → разветвленное соединение sshd → privsep sshd → пользовательская оболочка

напр. (изpstree -lp):

 init(1)-+
        .
         |-sshd(1015) +-sshd(1072)---sshd(1074)---bash(1075)

Процесс privsepsshd— это тот, который вы видите в netstat, окружение, которое вы читаете, происходит от его непосредственного потомка, оболочки (bash в этом примере ).

3
27.01.2020, 20:17

Основываясь на главной идее ответа , я написал простой скрипт для автоматизации процесса. Единственным аргументом является порт прослушивания, и он возвращает IP-адрес и исходящий порт клиента.

#!/bin/bash
PORT_TUNEL=$1
PID=`fuser $PORT_TUNEL/tcp 2>/dev/null`
# xargs is just used for trimming
PARENT_PID=`ps -p ${PID:-$$} -o ppid= | xargs`
netstat -ptn |  awk -v ppid="$PARENT_PID/sshd:"  '{if($7==ppid) print $5}'

Использование:

rsship 39963

Пример вывода:

67.214.221.43:26412

Пояснение:

Этот сценарий предполагает, что вы уже знаете, через какой порт прослушивания вы хотите получить IP-адрес клиента. Как объяснялось в других ответах, узнать это напрямую из самого соединения невозможно. Вместо этого нам нужно получить идентификатор процесса (pid ), который удерживает порт прослушивания. Для этого мы используем fuser и сохраняем его в переменной. Так как у fuser есть некоторый вывод в stderr, который может испортить наш код, мы перенаправляем его в /dev/null. Теперь у нас есть PID, который содержит порт прослушивания в нашей переменной $PID.

Следующим шагом будет получение родительского процесса, т. е. процесса, поддерживающего SSH-соединение с вашим клиентом. Для этого он использует ps. Xargs используется для обрезки вывода, так как он может содержать пробелы, которые позже испортят наш awk.

Наконец, он использует netstat для получения списка всех подключений и awk для отображения столбца 5, когда столбец 7 соответствует строке «$PARENT _PID/sshd :». Обратите внимание, что опция -v используется для правильной передачи переменной bash в awk. Я не собираюсь распространяться об этом, ищите «передача переменных bash в скрипт awk », если вам нужно больше информации об этом. Я объявляю переменную ppid, содержащую «$PARENT _PID/sshd :», текст, который я хочу сопоставить с 7-м столбцом. Мы используем это вместо grep, потому что 1150/sshd :будет соответствовать 150/sshd :. Есть несколько способов сделать это, но эта awk-команда была самой простой и удобочитаемой, которую я смог придумать .Это происходит после некоторых проблем, потому что при поиске только $PARENT _PID часто сопоставлялись некоторые случайные порты на разных соединениях, что давало неожиданные результаты.

Я знаю, что это можно было бы написать гораздо более компактно, но мне нравится, чтобы сценарии были читабельными и -не требующими пояснений с первого взгляда, когда это имеет смысл

Перечислитель прослушиваемых портов

У меня есть скрипт для отображения ВСЕХ прослушиваемых обратных туннелей на моей машине и получения IP-адреса их клиентов и исходящего порта:

В моей установке для этой цели есть специальный SSH-сервер, поэтому все подключения осуществляются через пользователя "sshtunnel". Вам придется изменить сценарий, если вы используете свой обычный сервер ssh, и придумать другой способ получить свой первый список прослушиваемых портов. использование «grep sshd» ПОЧТИ сделает свое дело, хотя в нем также будут перечислены порты прослушивания вашего основного сервера shh, хотя в МОЕЙ конкретной ситуации это работает, потому что сервер ssh был привязан к *, поэтому grep 127.0.0.1 отфильтрует его тоже:

#!/bin/bash

IP_SCRIPT="/etc/openvpn/rsship"

PORTS=`lsof -i -P -n | grep LISTEN | grep sshtunnel | grep 127.0.0.1 | awk -F" " '{print $9}' | awk -F":" '{print $2}' | awk '{if($1==$1+0 && $1>16000 && $1<16255) print $1}' | sort -n`


while IFS= read -r line; do
    REAL_IP=$($IP_SCRIPT $line)
    echo $line$'\t'$REAL_IP
done <<< "$PORTS"

Примечание :$IP _SCRIPT ссылается на первый опубликованный скрипт.

grep 127.0.0.1 используется для удаления строк ipv6 И тех, которые привязаны ко всем интерфейсам (, отмеченным в выходных данных звездочкой *)за один проход (в нашей настройке все IPv6 имеют аналоги IPv4 ).

Этот скрипт перечисляет только порты между 16000 и 16255 (, потому что это мой конкретный вариант использования ). Вы можете удалить всю часть awk, чтобы она принимала ЛЮБОЙ порт. Вот так:

#!/bin/bash

IP_SCRIPT="/etc/openvpn/rsship"

PORTS=`lsof -i -P -n | grep LISTEN | grep sshtunnel | grep 127.0.0.1 | awk -F" " '{print $9}' | awk -F":" '{print $2}' | sort -n`


while IFS= read -r line; do
    REAL_IP=$($IP_SCRIPT $line)
    echo $line$'\t'$REAL_IP
done <<< "$PORTS"

Часть lsof можно сделать лучше, но она уже была сделана, и, поскольку я торопился, я решил повторно использовать этот код, даже не задумываясь. В основном используется awk для разделения и печати определенного текста столбца (порта, в частности ). Как мы обычно говорим, :работает на моей машине. Если вы хотите улучшить его,используйте «lsof -i -P -n | grep LISTEN» и посмотрите, как вы можете сузить его еще лучше, поскольку моя строка может не подходить для вашего конкретного случая. Я не уверен на 100%, но думаю, что таких же результатов можно добиться, используя только netstat.

Если вы запускаете этот сценарий очень часто и имеете несколько портов, вы можете изменить его так, чтобы он вызывал netstat только один раз и снова и снова обрабатывал этот вывод, чтобы получить все данные.

1
22.12.2020, 19:56

Теги

Похожие вопросы