Замечательным примером сетевой солидарности являются многочисленные сервисы looking-glass, позволяющие заглянуть за кулисы очень многих больших и маленьких сетей во всём мире. Это настолько удивительно в современном мире, спрятанном за сотней систем безопасности, просто так взять и выполнить команды на маршрутизаторах являющихся одними из самых критичных устройств всей инфраструктуры передачи данных.

looking-glass version6


Надо лишь ввести IP адрес или префикс в поле и получить в ответ таблицу маршрутизации или трассировку и результаты работы утилиты ping. Поэтому когда понимаешь, что можно вводить не только адреса, но и некоторые другие символы сформированные в осмысленные команды и получать осмысленные результаты, наступает ступор. Хочется бежать и кричать на всех углах: «Да что же это такое надо немедленно запретить, что за несуразность?». Это всё последствия последних лет, когда безопасность превыше открытости и удобности и на это, несомненно, есть причины.

Речь пойдёт об очень популярной реализации looking-glass от version6.net и о том что-же можно получить от этого сервиса.

Если вам вдруг покажется обычным что интерфейс looking-glass позволяет вводить что-то кроме IP адреса, то вероятно вы относитесь к «старой школе» или не читаете новости. Мне показалось это необычным, тем более что другие реализации этого сервиса такого не позволяют.

  • У ReTN (достаточно популярная реализация) все введённые символы воспринимаются как доменное имя, если это не IP адрес.
  • MSX-IX всё разделено на части, вводить можно, но только там где это предусмотрено и интерпретируется всё достаточно жёстко.
  • Data IX позволяет некоторую свободу, хотя и сообщает что указан не IP адрес: «Указан недопустимый аргумент — должен быть IP или IP/n» — но всё равно выполняется birdc, который сообщает об ошибке и фильтрует все непотребства.
  • А Вконтакте разрешён только ping и traceroute и только с IP адресами.

Так как это было для меня необычным я даже начал предупреждать об этом владельцев сервисов, но потом заглянул в код и понял что так и должно быть — это фича, а не баг. На сайте version6.net, который сейчас почему-то не доступен, про функционал честно написано: "all BGP show commands, ping and traceroute".

Открываем lg.cgi, который читается достаточно тяжело и Perl здесь совсем не помогает:

my %FORM = &cgi_decode($incoming);
...
$FORM{addr} =~ s/\s.*// if (($FORM{query} eq "ping") || ($FORM{query} eq "trace"));
$FORM{addr} =~ s/[^\s\d\.:\w\-_\/\$]//g;

Команда передаётся в переменной $addr, в которой удаляются все символы кроме пробельных (включая табы, опция \s), букв, цифр, символов "-", "_", "/", "$", ".", ":".

Условие с ping значительно строже. Насколько я вижу вытирается весь ввод после пробельного символа. Поэтому добавить что-то лишнее в команду ping и traceroute значительно сложнее.

my $command = sprintf($query_cmd, $FORM{addr});
...
if ($FORM{addr} !~ /^[\w\.\^\$\-\/ ]*$/) {
	if ($FORM{addr} =~ /^[\w\.\^\$\-\:\/ ]*$/) {
...
	} else {
		&print_error("Illegal characters in parameter string");
	}
}

Потом формируется команда для непосредственного выполнения из шаблона $query_cmd и выполняется проверка на принадлежность ввода немного другой группе символов: исключаются табы, потому что явно указаны пробелы, символ "_" остаётся включённым потому что попадает под опцию \w вместе с цифрами, появляется символ "^". Дополнительная проверка делается на ":", которое возможно только при работе с IPv6.

Вот собственно и всё, оставшиеся проверки только на пустую строку для некоторых режимов работы. Команда для выполнения уже сформирована ранее и она без изменений уходит на устройство:

$FORM{addr} = "" if ($FORM{addr} =~ /^[ ]*$/);
...
if ($query_cmd =~ /%s/) {
	&print_error("Parameter missing") if ($FORM{addr} eq "");
} else {
	&print_warning("No parameter needed") if ($FORM{addr} ne "");
}
...
&run_command($FORM{router}, $router_list{$FORM{router}}, $command);

Что же мы можем? Из полезного потеряли кавычки, символы "|", "?" и все скобки. Но осталось очень много, даже очень. Шаблон формирующий команды выглядит вот так (для Cisco):

my %valid_query = (
	"ios"		=>	{
		"ipv4"			=>	{
			"bgp"			=>	"show ip bgp %s",
			"advertised-routes"	=>	"show ip bgp neighbors %s advertised-routes",
			"summary"		=>	"show ip bgp summary",
			"ping"			=>	"ping %s",
			"trace"			=>	"traceroute %s"
			},
...

Основные команды show ip bgp, ping и traceroute. Очевидно что show ip bgp summary и show ip bgp neighbors %s advertised-routes, можно сформировать из show ip bgp %s.

show ip bgp


Наш хлеб. Стоит отметить что на разных сайтах всё же производится дополнительная фильтрация, или доработка под другие системы отличные от стандартных, поэтому не всегда ввод произвольных символов возможен. Скорее даже он возможен, но дальнейшее выполнение команд приводит к ошибкам. Однако если мы имеем базовые устройства предусмотренные в оригинальном коде то можем вводить широкий спектр команд. Сайт Cisco, остановимся на одном вендоре, предлагает много вариантов. Немного полезных, для примера.

show ip bgp regexp


Смотрим все маршруты по заданному AS-PATH. Например, до всех сетей Yandex из Стокгольма, ТТК (GET отправит напрямую к результатам запроса):

show ip bgp regexp 13238$
Router: sgm01rb 
Command: show bgp regexp 13238$


Sat Dec 19 16:30:21.141 UTC
BGP router identifier 10.146.0.1, local AS number 20485
BGP generic scan interval 60 secs
BGP table state: Active
Table ID: 0x0   RD version: 0
BGP main routing table version 2995757495
BGP scan interval 60 secs

Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 20485:1 (default for vrf internet)
*>i5.45.192.0/18      10.78.0.6             1000     70      0 13238 i
* i                   10.99.0.8             1000     70      0 13238 i
*                     149.6.168.201         1000     70      0 174 13238 i
*                     166.63.220.185        1000     70      0 1273 9002 13238 i
*                     212.73.250.153        1000     60      0 3356 13238 i
*                     213.248.99.221        1000     70      0 1299 13238 i
*>i5.45.194.0/24      10.78.0.6             1000     70      0 13238 i
* i                   10.99.0.8             1000     70      0 13238 i
*                     212.73.250.153        1000     60      0 3356 13238 i
*                     213.248.99.221        1000     70      0 1299 13238 i
*>i5.45.196.0/24      10.78.0.6             1000     70      0 13238 i
* i                   10.99.0.8             1000     70      0 13238 i
*                     149.6.168.201         1000     70      0 174 13238 i
*                     166.63.220.185        1000     70      0 1273 9002 13238 i
*                     212.73.250.153        1000     60      0 3356 13238 i
*                     213.248.99.221        1000     70      0 1299 13238 i
*>i5.45.202.0/24      10.78.0.6             1000     70      0 13238 i
* i                   10.99.0.8             1000     70      0 13238 i
*                     212.73.250.153        1000     60      0 3356 13238 i
*                     213.248.99.221        1000     70      0 1299 13238 i
...

show ip bgp neighbors


Подробная информация об установленных соседствах. Команда иногда косвенно доступна в подсвеченном выводе при выполнении других команд. Например, подробная информация об одном из соседств Билайна в Ставрополе:

show ip bgp neighbors 10.255.0.2
Router: len244-bb.stv 
Command: show ip bgp neigh


BGP neighbor is 10.255.0.2,  remote AS 3216, external link
  BGP version 4, remote router ID 79.104.32.226
  BGP state = Established, up for 1y5w
  Last read 00:00:40, last write 00:00:14, hold time is 180, keepalive interval is 60 seconds
  Neighbor sessions:
    1 active, is not multisession capable
  Neighbor capabilities:
    Route refresh: advertised and received(new)
    Four-octets ASN Capability: advertised and received
    Address family IPv4 Unicast: advertised and received
    Multisession Capability: advertised
  Message statistics:
    InQ depth is 0
    OutQ depth is 0
    
                         Sent       Rcvd
    Opens:                  1          1
    Notifications:          0          0
    Updates:                1        352
    Keepalives:        631466     635532
    Route Refresh:          0          0
    Total:             631468     635885
  Default minimum time between advertisement runs is 30 seconds

 For address family: IPv4 Unicast
  Session: 10.255.0.2
  BGP table version 182470946, neighbor version 182470946/0
  Output queue size : 0
  Index 77
  77 update-group member
  Incoming update prefix filter list is B2B-BRAS-IN
  Outgoing update prefix filter list is DENY-ALL
  Slow-peer detection is disabled
  Slow-peer split-update-group dynamic is disabled
                                 Sent       Rcvd
  Prefix activity:               ----       ----
    Prefixes Current:               0          1 (Consumes 52 bytes)
    Prefixes Total:                 0        176
    Implicit Withdraw:              0          0
    Explicit Withdraw:              0        175
    Used as bestpath:             n/a          1
    Used as multipath:            n/a          0

                                   Outbound    Inbound
  Local Policy Denied Prefixes:    --------    -------
    prefix-list                       16426          0
    Well-known Community:         126392327        n/a
    Bestpath from this peer:            347        n/a
    Suppressed due to dampening:      15381        n/a
    Invalid Path:                   2886275        n/a
    Total:                        129310756          0
  Maximum prefixes allowed 500
  Threshold for warning message 75%, restart interval 3 min
  Number of NLRIs in the update sent: max 0, min 0
  Last detected as dynamic slow peer: never
  Dynamic slow peer recovered: never

Datagrams (max data segment is 1460 bytes):
Rcvd: 1268112 (out of order: 0), with data: 635885, total data bytes: 12089768
Sent: 1265174 (retransmit: 1 fastretransmit: 0),with data: 631468, total data bytes: 11997935

...

Можно расширить до advertised-routes, чтобы посмотреть какие маршруты анонсируются в сторону определённого соседа, часто присутствует непосредственно в интерфейсе.

show ip bgp summary


Команда не всегда доступна напрямую, поэтому можно попробовать выполнить в обход. Например, для РТКОММ:

show ip bgp summary
BGP router identifier 81.176.81.18, local AS number 8342 
RIB entries 1052472, using 64 MiB of memory 
Peers 2, using 5024 bytes of memory 
Peer groups 1, using 16 bytes of memory 

Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd 
195.161.1.10 4 8342 42323357 15458 0 0 0 01w3d17h 574623 
195.161.1.155 4 8342 43105981 15458 0 0 0 01w3d17h 574623 

Total number of neighbors 2

Ping и Traceroute


И эти команды можно расширить: увеличить размер пакета, выключить фрагментирование. Но сделать это сложнее, потому что код для фильтрации строже. Примеры, однако можно найти — Starnet, кстати здесь Juniper:

ping count 5 detail do-not-fragment size 1200 8.8.8.8
Router: MSK-IX MX480 
Command: ping count 5 detail do-not-fragment size 1200 8.8.8.8


PING 8.8.8.8 (8.8.8.8): 1200 data bytes
1208 bytes from 8.8.8.8 via xe-3/3/0.0: icmp_seq=0 ttl=60 time=1.041 ms
1208 bytes from 8.8.8.8 via xe-3/3/0.0: icmp_seq=1 ttl=60 time=0.964 ms
1208 bytes from 8.8.8.8 via xe-3/3/0.0: icmp_seq=2 ttl=60 time=0.959 ms
1208 bytes from 8.8.8.8 via xe-3/3/0.0: icmp_seq=3 ttl=60 time=32.190 ms
1208 bytes from 8.8.8.8 via xe-3/3/0.0: icmp_seq=4 ttl=60 time=1.038 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.959/7.238/32.190/12.476 ms
...

Looking-glass замечательный инструмент, даже отличный, решающий многие проблемы и сплачивающий ряды сетевых специалистов по всему миру, очень чёткий признак зрелости компании. Упомянув несколько разных компаний, в своей я пока не решился выставить подобный сервис наружу.

Экспериментировать можно долго, сервисов LG доступно очень много по всему миру и достаточное количество из них построено на версии предлагаемой version6.net. Но любой инструмент должен быть предсказуем, некоторые из нефильтруемых команд ужасно ресурсоёмки, некоторые открывают чуть больше чем можно позволить в современном мире. Загляните в свой код и сделайте так как вам будет достаточно. Будьте внимательны друг к другу, взаимовыручка и открытость позволили построить Интернет, не будем это разрушать.

Комментарии (13)


  1. JDima
    21.12.2015 13:53
    +3

    в своей я пока не решился выставить подобный сервис наружу.

    Да ничего особо страшного в этом нет. Берете какой-нибудь древний, не нужный роутер (или виртуалку с CSR1k). Делаете соседства с несколькими бордерами. На тех бордерах запрещаете принятие любых префиксов с того LG, и вообще выполняете все настройки как для вражеского роутера, например, ограждаете LG средствами ACL'ей, чтобы если кто-то каким-то образом получит на нем CLI, то никуда прыгнуть с него не сможет, настраиваете со всех сторон полисеры, storm control. Ну и делаете фронтенд на http, валидирующий команды по регулярным выражениям. Или не делаете, а просто пускаете людей по telnet/ssh, но с фильтрацией команд белым списком (по tacacs, RBAC или как угодно).

    Итого: если вы решите грохнуть абсолютно любой из найденных вами LG, то повлияет это только на сервис LG. Продакшн вы никому не обвалите. Надо быть идиотом, чтобы выделять под LG боевой роутер с продуктивным трафиком.


    1. urticazoku
      21.12.2015 14:21
      +3

      Долго думала при чем тут фирма LG и когда они начали выпускать роутеры. Потом дошло :)


    1. Loiqig
      21.12.2015 14:50

      Надо быть идиотом, чтобы выделять под LG боевой роутер с продуктивным трафиком.

      Вот summary с lg RETN Воронеж соседство с Эр-Телеком:
      Peer          AS       InPkt    OutPkt      OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
      87.245.243.62 9049     412381   45106746       0      18     19w0d1h Establ  inet.0: 185/773/769/0

      185 активных маршрутов в default таблице. Боевой у RETN роутер или нет? А у Эр-Телеком?


      1. JDima
        21.12.2015 14:59

        По обратке пир похож на принадлежащий RETN бордер с эр-телекомом. gw-ertelecom.retn.net.

        Сколько активных маршрутов — не особо важно для LG, хотя конечно странно, что оно в RIB пишется.


        1. JDima
          21.12.2015 15:07
          +1

          Хотя конечно странно, что ASN у пира чужой… Ну либо что-то хитрое делают, либо «безумству храбрых поем мы славу».


          1. Loiqig
            21.12.2015 17:18

            В том-то и дело, что такое много где.


            1. JDima
              21.12.2015 17:23
              +1

              Люди настолько уверены в отсутствии хотя бы элементарных багов? Взять любую версию IOS — у нее найдется что-то вроде «show run вызывает крэш».

              Ну не верю я, что кто-то будет давать посторонним какой угодно доступ к своему боевому железу. Что мешает взять какой-нибудь древний хлам и на него пускать?


              1. Loiqig
                21.12.2015 17:32

                А я верю, когда писал пост пролез достаточно много LG. Ввод везде фильтрован так как написано в статье, если попадается что-то не стандартное команда улетает дальше и там видны сообщения об ошибках с железки. Боевые соседства тоже вполне себе видны.
                Изначальное в этом же и был смысл, как мне кажется, это сейчас выглядит пугающе.


    1. k0ldbl00d
      22.12.2015 01:00

      Мы тут с коллегами интересуемся — а как при такой схеме смотреть, например, sh bgp summary или sh route receive-protocol bgp {neighbor}?


      1. JDima
        22.12.2015 08:08

        С какой целью, и что конкретно смущает?

        LG нужен в первую очередь чтобы посмотреть через него на свою AS.


  1. equand
    21.12.2015 13:57

    Я оставлю это здесь:
    github.com/ServerAstra/py-lookingglass

    Для быстрого решения работает неплохо. Буду дорабатывать, кому не лень дополняйте )


  1. phantasm1c
    22.12.2015 14:01

    Вообще не понимаю в чем сложность написания looking glass «под себя» и не использовать не пойми что от других. Это пишется за один вечер, с учётом просмотра мануалов по html и php (сам так и написал). Главное не забывать валидировать пользовательский ввод регекспами.


    1. Loiqig
      22.12.2015 18:38

      Так в этом и посыл. «Не пойми что от других», про который говорится в посте — очень, даже очень популярный вариант.