пятница, 17 декабря 2010 г.

Solaris IPFilter: NAT/PAT

По неизвестной мне причине, Solaris IPFilter менее распространен и документирован, чем его родственники из BSD-like клонов. Некоторые вещи, достаточно обыденные в рядовом применении, не вполне очевидны и не вполне тривиальны. Причем гугл, как показывает практика, в данных исследованиях практически бесполезен.

Давайте попытаемся восполнить этот пробел.

Выполним одну простую задачу и посмотрим, что у нас получится.

Итак, у нас есть машина с настроенным IPFilter. Для примера возьмем порт 22 (SSH), используя NAT/PAT, перебросим его на порт 2222.

Стартовая конфигурация IPFilter (/etc/ipf.conf):

#
# ipf.conf
#
# IP Filter rules to be loaded during startup
#
# See ipf(4) manpage for more information on
# IP Filter rules syntax.

# Bastion host
#
# Host with one interface:
# eri0 - internal (blade)
#
# Rules by Y.Voinov (C) 2007,2010

# Rules groups setup
# Group 100 - Blocked networks & packets on any interface
# Group 100 setup
block in all head 100
# Group 200 - Opened incoming ports on eri0
# Group 200 setup
pass in on eri0 head 200

# ---------------------
# Common blocking rules
# ---------------------

# Block all IP fragments
block in quick all with frag group 100

# Block all short IP fragments
block in quick proto tcp all with short group 100

# Block any IP packets with options set in them
block in quick all with ipopts group 100

# Block OS fingerprint attempts
block in log first quick proto tcp all flags SF/SF group 100
block in log first quick proto tcp all flags SF/SFRA group 100
block in log first quick proto tcp all flags /SFRA group 100
block in log first quick proto tcp all flags SFUP/SFUP group 100
block in log first quick proto tcp all flags FUP/FUP group 100
block in log first quick proto tcp all flags F/F group 100
block in log first quick proto tcp all flags U/U group 100
block in log first quick proto tcp all flags P/P group 100

# Pass ICMP Echo
# ------------ eri0 interface ------------
#pass in quick on eri0 proto icmp from 192.168.0.0/24 to blade icmp-type echo keep state
#pass out quick on eri0 proto icmp from blade to 192.168.0.0/24 icmp-type echorep keep state
# ------------ eri0 interface ------------

# Stealth for traceroute (hide as hop)
# ------------ eri0 interface ------------
#block in quick on eri0 fastroute proto udp from any to any port 33434
>< 33465
# ------------ eri0 interface ------------

# Anti-spoofing rules
#block in quick from 192.168.0.0/16 to any group 100
block in quick from 172.16.0.0/12 to any group 100
block in quick from 10.0.0.0/8 to any group 100
block in quick from 127.0.0.0/8 to any group 100
block in quick from 0.0.0.0/8 to any group 100
block in quick from 169.254.0.0/16 to any group 100
block in quick from 192.0.2.0/24 to any group 100
block in quick from 204.152.64.0/23 to any group 100
block in quick from 224.0.0.0/3 to any group 100

# ------------ eri0 interface ------------
# 21 port - FTP service. Disable port and service on Internet servers!
#pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=21 flags S keep state group 200
# 22 port - SSH
pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=22 flags S keep state group 200
# 80 port - HTTP
pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=80 flags S keep state group 200
# 177 port - x11 service. Disable port and service on Internet servers!
pass in quick on eri0 proto udp from 192.168.100.0/24 to blade port=177 keep state group 200
# 443 port - HTTPS
pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=443 flags S keep state group 200
# 2222 port - SSH Alternative
#pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=2222 flags S keep state group 200
# 1158 port - OEM console.
# Note: Secure console on Internet servers!
#pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=1158 flags S keep state group 200
# Note: OEM console may be on port 5500
#pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=5500 flags S keep state group 200
# 1521 port - Oracle. Disable port on Internet servers!
pass in quick on eri0 proto tcp from 192.168.100.0/24 to blade port=1521 flags S keep state group 200
# 7777 port - OHS. Disable port when using WebCache.
#pass in quick on eri0 proto tcp from any to blade port=7777 flags S keep state group 200
# 8888 port - OC4J main http port.
# Disable port after mount with mod_oc4j using AJP13.
#pass in quick on eri0 proto tcp from any to blade port=8888 flags S keep state group 200
# 9400 port - WebCache admin default port.
#pass in quick on eri0 proto tcp from any to blade port=9400 flags S keep state group 200
# ------------ eri0 interface ------------

# 53 port - DNS.
# ------------ eri0 interface ------------
# Allow incoming DNS requests to server
#pass in quick on eri0 proto tcp/udp from any to blade port=domain keep state group 200
# ------------ eri0 interface ------------

# 123 port - NTP.
# ------------ eri0 interface ------------
# Allow incoming NTP requests to server
#pass in quick on eri0 proto udp from any to blade port=ntp keep state group 200
# ------------ eri0 interface ------------

# Outgoing and callbacks sessions
# Allow connections originating from local machine out
pass out quick proto tcp/udp from any to any keep state keep frags
pass out quick proto icmp from any to any keep state

# Finally block all unmatched
block in quick all

Итак, порт 22 открыт. Напишем конфигурацию ipnat.conf:

rdr eri0 0.0.0.0/0 port 2222 -
> 0/32 port 22

Некоторые пояснения к правилу. Слева написан адрес 0.0.0.0/0, что означает любой адрес. Мы можем с таким же успехом (и в нашем случае это будет более правильно) написать 192.168.0.0/16, однако мы хотели получить наиболее общее правило, которое не требуется менять в случае изменения адресов сетей; кроме того, ограничения доступа из сетей и адресов энфорсятся в нашем случае правилами ipf.conf. Адрес 0/32 справа не ошибка. Он означает - "использовать адрес, назначенный интерфейсу". Конечно, там можно попытаться написать и 127.0.0.1, однако тогда редирект не будет работать.

Обратите внимание: правила ipnat.conf применяются в порядке написания (так же, как и правила ipf.conf) и выполняются ДО применения правил ipf.conf.

Перезапустим IPFilter и проверим состояние наших правил:

root @ blade / # ipnat -l
List of active MAP/Redirect filters:
rdr eri0 0.0.0.0/0 port 2222 -
> 0.0.0.0/32 port 22 tcp

List of active sessions:
RDR 192.168.100.5 22
<- -> 192.168.100.5 2222 [192.168.100.1 2510]
RDR 192.168.100.5 22
<- -> 192.168.100.5 2222 [192.168.100.1 2506]

Редирект работает, соединения устанавливаются.

Еще раз обратите внимание на конфигурацию ipf.conf. Порт 2222 в основной конфигурации закрыт. Поскольку правила NAT выполняются до основных правил фильтра, наше правило PAT создает еще один открытый порт 2222 и редиректит его на открытый порт 22. Причем порт 22 тоже открыт, с ним можно соединиться.

Это можно проверить сканером портов:

Starting Nmap 5.21 ( http://nmap.org ) at 2010-12-17 15:35 Центральная Азия (зима)
NSE: Loaded 36 scripts for scanning.
Initiating ARP Ping Scan at 15:36
Scanning blade (192.168.100.5) [1 port]
Completed ARP Ping Scan at 15:36, 0.49s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 15:36
Scanning blade (192.168.100.5) [1000 ports]
Discovered open port 22/tcp on 192.168.100.5
Discovered open port 2222/tcp on 192.168.100.5
Completed SYN Stealth Scan at 15:36, 5.45s elapsed (1000 total ports)
Initiating Service scan at 15:36
Scanning 2 services on blade (192.168.100.5)
Completed Service scan at 15:36, 0.22s elapsed (2 services on 1 host)
Initiating OS detection (try #1) against blade (192.168.100.5)
Retrying OS detection (try #2) against blade (192.168.100.5)
NSE: Script scanning 192.168.100.5.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 15:36
Completed NSE at 15:36, 1.28s elapsed
NSE: Script Scanning completed.

Nmap scan report for blade (192.168.100.5)
Host is up (0.0024s latency).
Not shown: 995 filtered ports

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 5.6p1-hpn13v10 (protocol 2.0)
| ssh-hostkey: 1024 72:8e:3f:d4:91:77:85:39:2a:71:f1:a5:13:b1:62:c1 (DSA)
|_2048 57:b7:86:57:0c:c7:9b:cd:b6:90:e4:e8:18:0b:c0:c6 (RSA)
80/tcp closed http
443/tcp closed https
1521/tcp closed oracle
2222/tcp open ssh OpenSSH 5.6p1-hpn13v10 (protocol 2.0)
| ssh-hostkey: 1024 72:8e:3f:d4:91:77:85:39:2a:71:f1:a5:13:b1:62:c1 (DSA)
|_2048 57:b7:86:57:0c:c7:9b:cd:b6:90:e4:e8:18:0b:c0:c6 (RSA)

MAC Address: 00:03:BA:10:D0:86 (Sun Microsystems)

OS fingerprint not ideal because: Didn't receive UDP response. Please try again with -sSU
No OS matches for host
Uptime guess: 0.098 days (since Fri Dec 17 13:14:53 2010)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=258 (Good luck!)
IP ID Sequence Generation: Incremental

HOP RTT ADDRESS
1 2.35 ms blade (192.168.100.5)

Read data files from: H:\Program Files\Nmap

OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .

Nmap done: 1 IP address (1 host up) scanned in 20.42 seconds
Raw packets sent: 2079 (96.514KB) | Rcvd: 25 (1306B)

Как видно, редирект нашего порта выглядит как еще один открытый порт.

Разумеется, данный пример совершенно абстрактен. Более политкорректно и правильно перебросить SSH прямо на порт 2222 настройками конфигурации сервиса :). Однако мы выбрали данный пример не для практических целей, а дабы убедиться в порядке применения правил IPFilter.

PS. Правила редиректа портов по такому принципу можно использовать при реализации прозрачных прокси с использованием, например, сервера Squid. Я напишу об этом более подробно в одной из следующих статей.