Как обнаружить прозрачный прокси (transparent proxy)

Иногда бывает нужно определить наличие такого прокси, допустим, при тестировании вэб-приложений. Непрозрачный прокси обнаруживается достаточно легко по source/dest IP и заголовкам, которые добавляет прокси. Оговорюсь, что мы будем слушать трафик на стороне клиента и сервера OS для анализа.

Итак, обнаружение прозрачного прокси. Для этого надо сделать запрос на заведомо несуществующий IP, к примеру, на 192.168.100.100. Прокси перехватит соединение (connection) и попытается обслужить его. Когда он определит, что не доступен сервер назначения, он, возможно, вернет статус ошибки или просто закроет соединение с клиентом. Большинство браузеров сгенерируют страницу с ошибкой, если они могут соединиться с сервером. В случае, если соединение было принято, но потом закрыто, страница с ошибкой будет отличаться.

Запрос с помощью curl на этот IP:

curl -Lv -o /dev/null -A "Firefox" "http://192.168.100.100/index.html"
* About to connect() to 192.168.100.100 port 80 (#0)
*   Trying 192.168.100.100... connected
* Connected to 192.168. 100.100 (192.168.100.100 ) port 80 (#0)
> GET /index.html HTTP/1.1
> User-Agent: Firefox
> Host: 192.168.100.100
> Accept: */*
>
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:03:30 --:--:--     0
< HTTP/1.1 502 internal error - server connection terminated
< Date: Thu, 17 Jul 2014 08:26:27 GMT
< Connection: keep-alive
< Cache-Control: no-store
< Content-Type: text/html
< Content-Language: en
< Content-Length: 294
<
{ [data not shown]

В данном трафике 100.100.100.100 — это IP клиента.

 1 0.000000 100.100.100.100 -> 192.168.100.100 TCP 76 0 3988560025 0x0002 56280 > http [SYN] Seq=3988560025 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3585329416 TSecr=0 WS=128
 2 0.001000 192.168.100.100 -> 100.100.100.100 TCP 76 0 3988560026 1365204930 0x0012 http > 56280 [SYN, ACK] Seq=1365204930 Ack=3988560026 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=4134164061 TSecr=3585329416 WS=128
 3 0.001000 100.100.100.100 -> 192.168.100.100 TCP 68 0 1365204931 3988560026 0x0010 56280 > http [ACK] Seq=3988560026 Ack=1365204931 Win=14720 Len=0 TSval=3585329417 TSecr=4134164061
 4 0.001000 100.100.100.100 -> 192.168.100.100 HTTP 196 128 1365204931 3988560026 0x0018 GET /index.html HTTP/1.1
 5 0.001000 192.168.100.100 -> 100.100.100.100 TCP 68 0 3988560154 1365204931 0x0010 http > 56280 [ACK] Seq=1365204931 Ack=3988560154 Win=15616 Len=0 TSval=4134164062 TSecr=3585329417
 6 210.944720 192.168.100.100 -> 100.100.100.100 HTTP 578 510 3988560154 1365204931 0x0018 HTTP/1.1 502 internal error - server connection terminated (text/html)
 7 210.945720 100.100.100.100 -> 192.168.100.100 TCP 68 0 1365205441 3988560154 0x0010 56280 > http [ACK] Seq=3988560154 Ack=1365205441 Win=15744 Len=0 TSval=3585540394 TSecr=4134375004
 8 210.945720 100.100.100.100 -> 192.168.100.100 TCP 68 0 1365205441 3988560154 0x0011 56280 > http [FIN, ACK] Seq=3988560154 Ack=1365205441 Win=15744 Len=0 TSval=3585540394 TSecr=4134375004
 9 210.955719 192.168.100.100 -> 100.100.100.100 TCP 68 0 3988560155 1365205441 0x0011 http > 56280 [FIN, ACK] Seq=1365205441 Ack=3988560155 Win=15616 Len=0 TSval=4134375015 TSecr=3585540394
 10 210.955719 100.100.100.100 -> 192.168.100.100 TCP 68 0 1365205442 3988560155 0x0010 56280 > http [ACK] Seq=3988560155 Ack=1365205442 Win=15744 Len=0 TSval=3585540404 TSecr=4134375015

Как мы видим, соединение к несуществующему хосту было принято и на него отправлен запрос GET. Но данных в ответ не получено, прокси вернул код ошибки и закрыл соединение.

В случае, если прокси в цепочке передачи данных нет, вывод curl-a будет такой:

curl -Lv -o /dev/null -A "Firefox" "http://192.168.100.100/index.html"
* About to connect() to 192.168.100.100 port 80 (#0)
*   Trying 192.168.100.100... Connection timed out
* couldn't connect to host
* Closing connection #0
curl: (7) couldn't connect to host

А перехваченный трафик будет примерно таким:

 1 0.000000 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586242734 TSecr=0 WS=128
 2 0.999847 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 [TCP Retransmission] 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586243734 TSecr=0 WS=128
 3 2.999541 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 [TCP Retransmission] 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586245734 TSecr=0 WS=128
 4 6.998929 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 [TCP Retransmission] 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586249734 TSecr=0 WS=128
 5 14.997705 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 [TCP Retransmission] 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586257734 TSecr=0 WS=128
 6 30.995257 100.100.100.100 -> 192.168.100.100 TCP 76 0 885915575 0x0002 [TCP Retransmission] 56285 > http [SYN] Seq=885915575 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3586273734 TSecr=0 WS=128

Второй способ обнаружить прозрачный прокси — сравнить значения TCP SEQ/ACK на стороне клиента и сервера OS. Будем считать, что мы можем снять трафик и на стороне прокси – это нужно просто для наглядности того, какие значения надо сравнивать.

Трафик на стороне клиента (100.100.100.100):

1   0.000000000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774121              14600  2   57895 > http [SYN] Seq=1865774121 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3604767069 TSecr=0 WS=128
2   0.000000000  200.200.200.200  100.100.100.100  TCP     80      57895   4096028741  1865774122  14480  18  http > 57895 [SYN, ACK] Seq=4096028741 Ack=1865774122 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=4153598607 TSecr=3604767069 WS=128
3   0.000000000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774122  4096028742  14720  16  57895 > http [ACK] Seq=1865774122 Ack=4096028742 Win=14720 Len=0 TSval=3604767072 TSecr=4153598607
4   0.000000000  100.100.100.100  200.200.200.200  HTTP    57895   80      1865774122  4096028742  14720  24  GET /images/new.jpg HTTP/1.1
5   0.000000000  200.200.200.200  100.100.100.100  TCP     80      57895   4096028742  1865774234  14592  16  http > 57895 [ACK] Seq=4096028742 Ack=1865774234 Win=14592 Len=0 TSval=4153598607 TSecr=3604767072
6   0.162975000  200.200.200.200  100.100.100.100  TCP     80      57895   4096028742  1865774234  14592  16  [TCP segment of a reassembled PDU]
7   0.162975000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774234  4096035982  17536  16  57895 > http [ACK] Seq=1865774234 Ack=4096035982 Win=17536 Len=0 TSval=3604767235 TSecr=4153598769
8   0.162975000  200.200.200.200  100.100.100.100  TCP     80      57895   4096035982  1865774234  14592  16  [TCP segment of a reassembled PDU]
9   0.162975000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774234  4096037430  20480  16  57895 > http [ACK] Seq=1865774234 Ack=4096037430 Win=20480 Len=0 TSval=3604767235 TSecr=4153598770
10  0.162975000  200.200.200.200  100.100.100.100  HTTP    80      57895   4096037430  1865774234  14592  24  HTTP/1.1 200 OK  (JPEG JFIF image)

Трафик на стороне прокси (200.200.200.200):

1   0.000000000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774121              14600  2   57895 > http [SYN] Seq=1865774121 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3604767069 TSecr=0 WS=128
2   0.000000000  200.200.200.200  100.100.100.100  TCP     80      57895   4096028741  1865774122  14480  18  http > 57895 [SYN, ACK] Seq=4096028741 Ack=1865774122 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=4153598607 TSecr=3604767069 WS=128
3   0.000000000  100.100.100.100  200.200.200.200  TCP     57895   80      1865774122  4096028742  14720  16  57895 > http [ACK] Seq=1865774122 Ack=4096028742 Win=14720 Len=0 TSval=3604767072 TSecr=4153598607
4   0.000000000  100.100.100.100  200.200.200.200  HTTP    57895   80      1865774122  4096028742  14720  24  GET /images/new.jpg HTTP/1.1
5   0.000000000  200.200.200.200  100.100.100.100  TCP     80      57895   4096028742  1865774234  14592  16  http > 57895 [ACK] Seq=4096028742 Ack=1865774234 Win=14592 Len=0 TSval=4153598607 TSecr=3604767072
6   0.120001000  100.100.100.100  200.200.200.200  TCP     57895   80      1318499263              14600  2   [TCP Port numbers reused] 57895 > http [SYN] Seq=1318499263 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=4153598725 TSecr=0 WS=128
7   0.120001000  200.200.200.200  100.100.100.100  TCP     80      57895   3611911297  1318499264  14480  18  http > 57895 [SYN, ACK] Seq=3611911297 Ack=1318499264 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=1923501909 TSecr=4153598725 WS=128
8   0.120001000  100.100.100.100  200.200.200.200  TCP     57895   80      1318499264  3611911298  14720  16  57895 > http [ACK] Seq=1318499264 Ack=3611911298 Win=14720 Len=0 TSval=4153598727 TSecr=1923501909
9   0.121001000  100.100.100.100  200.200.200.200  HTTP    57895   80      1318499264  3611911298  14720  24  GET /images/new.jpg HTTP/1.1
10  0.121001000  200.200.200.200  100.100.100.100  TCP     80      57895   3611911298  1318499376  14592  16  http > 57895 [ACK] Seq=3611911298 Ack=1318499376 Win=14592 Len=0 TSval=1923501910 TSecr=4153598728

Трафик на стороне OS:

1   0.000000000  100.100.100.100  200.200.200.200  TCP     57895   80      1318499263              14600  2   57895 > http [SYN] Seq=1318499263 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=4153598725 TSecr=0 WS=128
2   0.000038000  200.200.200.200  100.100.100.100  TCP     80      57895   3611911297  1318499264  14480  18  http > 57895 [SYN, ACK] Seq=3611911297 Ack=1318499264 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=1923501909 TSecr=4153598725 WS=128
3   0.000204000  100.100.100.100  200.200.200.200  TCP     57895   80      1318499264  3611911298  14720  16  57895 > http [ACK] Seq=1318499264 Ack=3611911298 Win=14720 Len=0 TSval=4153598727 TSecr=1923501909
4   0.001117000  100.100.100.100  200.200.200.200  HTTP    57895   80      1318499264  3611911298  14720  24  GET /images/new.jpg HTTP/1.1
5   0.001141000  200.200.200.200  100.100.100.100  TCP     80      57895   3611911298  1318499376  14592  16  http > 57895 [ACK] Seq=3611911298 Ack=1318499376 Win=14592 Len=0 TSval=1923501910 TSecr=4153598728
6   0.001886000  200.200.200.200  100.100.100.100  TCP     80      57895   3611911298  1318499376  14592  16  [TCP segment of a reassembled PDU]
7   0.001924000  200.200.200.200  100.100.100.100  TCP     80      57895   3611914194  1318499376  14592  16  [TCP segment of a reassembled PDU]
8   0.001930000  200.200.200.200  100.100.100.100  TCP     80      57895   3611918538  1318499376  14592  16  [TCP segment of a reassembled PDU]
9   0.001937000  200.200.200.200  100.100.100.100  HTTP    80      57895   3611919986  1318499376  14592  24  HTTP/1.1 200 OK  (JPEG JFIF image)
10  0.002162000  100.100.100.100  200.200.200.200  TCP     57895   80      1318499376  3611914194  17536  16  57895 > http [ACK] Seq=1318499376 Ack=3611914194 Win=17536 Len=0 TSval=4153598729 TSecr=1923501911

Как мы видим значения SEQ/ACK одинаковы в направлении от клиента к прокси и отличаются в направлении к OS. По другим капчам замечено, что прокси иногда меняет TCP window scale, но на этот признак полагаться не стоит.
Заметим, что на стороне прокси пакеты «дублируются» — прокси принимает пакет от клиента и переправляет на OS.

И, наконец, последний способ. Он базируется на предположении из первого метода — прокси сначала принимает соединение от клиента и только после этого делает запрос на OS. Т.е. Мы можем измерить задержку между клиентским и серверным SYN и SYN/ACK. Если известно, что OS расположен далеко, а задержка в районе 1-10 миллисекунд, то можно сделать вывод о наличии прокси.

Перехвачен трафик без прокси (оставлены только существенные пакеты SYN и SYN/ACK; прокси — 173.194.113.52 ):

  1   0.000000  100.100.100.100 -> 173.194.113.52 TCP  64204463 14600  0x0002 43102 > http [SYN] Seq=64204463 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3669511612 TSecr=0 WS=128
  2   0.031995 173.194.113.52 -> 100.100.100.100  TCP 64204464 2342845794 42540  0x0012 http > 43102 [SYN, ACK] Seq=2342845794 Ack=64204464 Win=42540 Len=0 MSS=1430 SACK_PERM=1 TSval=831970729 TSecr=3669511612 WS=64
  3   0.031995  100.100.100.100 -> 173.194.113.52 TCP 2342845795 64204464 14720 128 0x0010 43102 > http [ACK] Seq=64204464 Ack=2342845795 Win=14720 Len=0 TSval=3669511644 TSecr=831970729
  4   0.031995  100.100.100.100 -> 173.194.113.52 HTTP 2342845795 64204464 14720 128 0x0018 GET / HTTP/1.1

Как мы видим, задержка между SYN и SYN/ACK примерно 32 миллисекунды.

Трафик при наличии прокси:

  1   0.000000  100.100.100.100 -> 173.194.113.52 TCP  278229736 14600  0x0002 43103 > http [SYN] Seq=278229736 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSval=3669576737 TSecr=0 WS=128
  2   0.001999 173.194.113.52 -> 100.100.100.100  TCP 278229737 96176689 14480  0x0012 http > 43103 [SYN, ACK] Seq=96176689 Ack=278229737 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=4218397903 TSecr=3669576737 WS=128
  3   0.001999  100.100.100.100 -> 173.194.113.52 TCP 96176690 278229737 14720 128 0x0010 43103 > http [ACK] Seq=278229737 Ack=96176690 Win=14720 Len=0 TSval=3669576739 TSecr=4218397903
  4   0.001999  100.100.100.100 -> 173.194.113.52 HTTP 96176690 278229737 14720 128 0x0018 GET / HTTP/1.1

Задержка (0.001999) стала гораздо меньше из-за того, что расстояние от клиента до прокси меньше расстояния от клиента до OS. Данный метод не совсем надежен, т. к. прокси может быть расположен примерно посередине между клиентом и OS и задержки будут одинаковыми.

You can leave a response, or trackback from your own site.

Leave a Reply