Пинговать собственный IP-адрес в обход ядра

Интересно, есть ли способ обойти ядро ​​и перенаправить пакет ping на мой сетевой шлюз, когда я проверяю свой IP-адрес.

Например, мой частный IP-адрес - 172.31.42.99, а IP-адрес шлюза - 172.31.32.1. Что я хочу сделать, так это когда я сделаю "ping 172.31.42.99", я получу результат "ping 172.31.32.1".

Я не эксперт по таблице IP-маршрутизации или iptables, я не уверен, что там есть способ отредактировать таблицу маршрутизации или iptables для достижения этой цели?

Я пытался редактировать таблицы маршрутизации, используя sudo ip route add 172.31.42.99/32 через 172.31.32.1 , а также пытался редактировать цепочки iptables PREROUTING в нац табл. Ни один из них не работал.

Я ценю любую помощь или идеи.

1
задан 11 April 2020 в 01:51
1 ответ

ОБНОВЛЕНИЕ: давая здесь более точный ответ на

, когда я сделаю «ping 172.31.42.99», я получу результат «ping 172.31.32.1».

и не требует какой-либо специальной маршрутизации и не требует, чтобы 172.31.32.1 был маршрутизатором: простой DNAT.

с использованием ловушек netfilter OUTPUT

Сетевой стек linux имеет перехватчики netfilter, вставленные между различными этапами маршрутизации, как можно увидеть на этой схеме . Следует отметить, что входящие пакеты не обрабатываются в том же месте, что и исходящие пакеты, отправленные локально. В то время как перехватчики netfilter для первого находятся в перехватчиках PREROUTING, перехватчики для последнего находятся в перехватчиках OUTPUT: именно там должно быть помещено правило nat, а не в nat / PREROUTING, которое не будет видеть этот трафик. Поскольку я не знаю, что еще существует, на всякий случай я вставляю его перед любым другим правилом:

iptables -t nat -I OUTPUT -p icmp -d 172.31.42.99 -j DNAT --to-destination 172.31.32.1

Действия, выполненные в перехватчиках OUTPUT, могут запускать проверку перенаправления (как показано на предыдущей схеме): изменить первоначально выбранный маршрут для данного пакета. Обратите внимание, что это не влияет на другие характеристики IP-пакета: например, исходный IP-адрес не изменяется. Для конкретного случая OP это нормально, источник уже будет правильным. Во многих других случаях также необходимо внести другие неудобные изменения (например, SNAT в nat / POSTROUTING).

# ping 172.31.42.99
PING 172.31.42.99 (172.31.42.99) 56(84) bytes of data.
64 bytes from 172.31.42.99: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 172.31.42.99: icmp_seq=2 ttl=64 time=0.122 ms
64 bytes from 172.31.42.99: icmp_seq=3 ttl=64 time=0.105 ms
^C
--- 172.31.42.99 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 89ms
rtt min/avg/max/mdev = 0.090/0.105/0.122/0.017 ms

одновременно:

# conntrack -E -p icmp
    [NEW] icmp     1 30 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 [UNREPLIED] src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029
 [UPDATE] icmp     1 30 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029

(некоторое время спустя)

[DESTROY] icmp     1 src=172.31.42.99 dst=172.31.42.99 type=8 code=0 id=2029 src=172.31.32.1 dst=172.31.42.99 type=0 code=0 id=2029

Эквивалент с использованием nftables вместо iptables мог быть:

# nft add table ip mynat
# nft add chain ip mynat dnaticmp '{ type nat hook output priority -100; policy accept; }'
# nft add rule ip mynat dnaticmp ip protocol icmp ip daddr 172.31.42.99 dnat to 172.31.32.1

Предыдущий ответ основан на выполнении трюки с таблицами маршрутизации

... что, вероятно, не было тем, что задумал OP

Я даю вам достаточно веревки, чтобы повеситься.

Предварительное условие (заполняется OP): 172.31.32.1 должен быть маршрутизатором (и его предполагаемое поведение было протестировано ниже только с маршрутизатором Linux , поэтому он также может быть маршрутизатором Linux в случае, если поведение меняется).

Я предполагаю (не указано в OP), что IP-сеть - это 172.31.32.0/20, а сетевой интерфейс системы называется eth0 .

Причина, по которой вам не удалось изменить результаты путем изменения visible маршрутов, заключается в том, что при добавлении адреса к интерфейсу некоторые маршруты также автоматически добавляются в ... hidden ] локальная таблица маршрутизации. Эта таблица имеет самый низкий приоритет приоритета, потому что она вызывается из правила приоритет 0:

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

# ip route show table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 
broadcast 172.31.32.0 dev eth0 proto kernel scope link src 172.31.42.99 
local 172.31.42.99 dev eth0 proto kernel scope host src 172.31.42.99 
broadcast 172.31.47.255 dev eth0 proto kernel scope link src 172.31.42.99 

# ip route get from 172.31.42.99 172.31.42.99
local 172.31.42.99 from 172.31.42.99 dev lo uid 0 
    cache <local> 

Здесь цель состоит в том, чтобы переопределить для локального случая предыдущую запись. Единственный способ - "переместить" правило 0 в значение с более высоким приоритетом, чтобы иметь возможность вставить что-то перед:

# ip rule add pref 100 from all lookup local
# ip rule delete pref 0

И добавить правило, которое переопределит маршруты в более новую таблицу маршрутизации, но только для случая вывода, созданного локально, который переводится в специальный синтаксис iif lo , на самом деле означающий исходящий , а не из интерфейса lo :

# ip rule add pref 50 iif lo lookup 500

и необходимый маршрут (который позаботится разрешения ARP путем установки IP-адреса маршрутизатора в качестве шлюза):

# ip route add table 500 172.31.42.99/32 via 172.31.32.1

Теперь у нас есть два действительных маршрута (так что каждое направление будет даже проходить Strict Reverse Path Forwarding при замене интерфейсов: eth0 и 10 ).

  • добавлен специальный маршрут:

     # ip route get from 172.31.42.99 172.31.42.99
    172.31.42.99 из 172.31.42.99 через 172.31.32.1 dev eth0 table 500 uid 0
    тайник
    
  • а также, только с тех пор стали действительными в обратном направлении:

     # ip route get from 172.31.42.99 iif eth0 172.31.42.99
    local 172.31.42.99 из 172.31.42.99 dev lo table local
    кеш <локальный> iif eth0
    

Результат:

# ping 172.31.42.99
PING 172.31.42.99 (172.31.42.99) 56(84) bytes of data.
From 172.31.32.1: icmp_seq=1 Redirect Host(New nexthop: 172.31.42.99)
64 bytes from 172.31.42.99: icmp_seq=1 ttl=63 time=0.147 ms
From 172.31.32.1: icmp_seq=2 Redirect Host(New nexthop: 172.31.42.99)
64 bytes from 172.31.42.99: icmp_seq=2 ttl=63 time=0.129 ms
From 172.31.32.1: icmp_seq=3 Redirect Host(New nexthop: 172.31.42.99)
[...]

Это работает только потому, что 172.31.32.1 является маршрутизатором. Что на самом деле происходит для одного пинга:

  • система отправляет ICMP-запрос на настроенный шлюз: маршрутизатор,
  • маршрутизатор обнаруживает, что система неправильно настроена, и есть лучший прямой пункт назначения в той же локальной сети (которая оказывается система) для обработки этого запроса и отправляет перенаправление ICMP, чтобы сообщить ему, что нужно исправить свое поведение. Узел без маршрутизации просто отбросил бы пакет, маршрутизатор
  • по-прежнему направляет эхо-запрос ICMP в пункт назначения. 172.31.42.99: обратно отправителю,
  • система получает эхо-запрос ICMP (с действительным маршрутом и даже передавая правила строгой переадресации обратного пути) и отправляет обратно ответ ICMP таким же образом, как и раньше, маршрутизатор
  • снова отправляет перенаправление ICMP, маршрутизатор
  • по-прежнему направляет ответ ICMP, система
  • (и команда ping) получает Ответ ICMP.
2
ответ дан 11 April 2020 в 02:14

Теги

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