在不少系统中,ifconfig的时候,会出来一个ipfw0界面,注意最后一个字符中“零”,有人会问有没有ipfw1(壹)?回答是:可以有。
这是为什么呢?
自从FreeBSD9.0以后,IPFW添加了一个虚拟的日志接口,看来读一下ipfw的man:
……
log [logamount number]
Packets matching a rule with the log keyword will be made available for logging in two ways: if the sysctl variable net.inet.ip.fw.verbose is set to 0 (default), one can use bpf(4) attached to the ipfw0 pseudo interface.
当数据包匹配了带有log关键字的规则时,有两种方式进行记录:如果内核变量net.inet.ip.fw.verbose为0(默认值为零,译注:可以在内核配置文件中修改),就可以使用bpf(4)来连接ipfw0这个虚拟网卡。
This pseudo interface can be created after a boot manually by using the following command:
# ifconfig ipfw0 create
Or, automatically at boot time by adding the following line to the rc.conf(5) file:
firewall_logif="YES"
这个虚拟网卡可以使用ifconfig来创建:
# ifconfig ipfw0 create
或者可以在rc.conf中添加下面一行:
firewall_logif="YES"
There is no overhead if no bpf(4) is attached to the pseudo interface.
在没有bfp连接的时候,这个虚拟界面不会有任何开销。
If net.inet.ip.fw.verbose is set to 1, packets will be logged to syslogd(8) with a LOG_SECURITY facility up to a maximum of logamount packets. If no logamount is specified, the limit is taken from the sysctl variable net.inet.ip.fw.verbose_limit. In both cases, a value of 0 means unlimited logging.
Once the limit is reached, logging can be re-enabled by clearing the logging counter or the packet counter for that entry, see the resetlog command.
如果内核变量net.inet.ip.fw.verbose为1,则使用syslogd(3)来使用LOG_SECURITY设备来记录,记录的数据包数最大值为指定的logamount,如果没有指定logamount,则使用内核变量net.inet.ip.fw.verbose_limit。如果logamount或net.inet.ip.fw.verbose_limit值为零,则表示没有任何限制,将一直记录。
一旦达到了记录的最大值,记录将会停止,可以通过重置log计数器或数据包计数器的方式来重新激活记录功能。
Note: logging is done after all other packet matching conditions have been successfully verified, and before performing the final action (accept, deny, etc.) on the packet.
……
日志记录的时间是:所有的条件完成匹配之后,进行最后的动作(accept,deny等)之前。
这段说的比较清楚,ipfw的日志可以使用log关键字,记录的方式根据net.inet.ip.fw.verbose值分为两种,一种是传统的log方式,另一种是虚拟网卡的方式。
这两种有什么区别呢?
传统的方式使用syslogd来记录,如果不加特殊配置的话,就记录在/var/log/security里面,日志像下面的样子:
Jun 5 22:49:58 mm kernel: ipfw: 40 Reset TCP 192.168.82.253:21420 192.168.1.100:22 in via re0
Jun 5 22:50:31 mm kernel: ipfw: 40 Reset TCP 192.168.146.253:38534 192.168.1.100:22 in via re0
Jun 5 22:51:48 mm kernel: ipfw: 40 Reset TCP 192.168.35.253:18943 192.168.1.100:22 in via re0
Jun 5 22:52:07 mm kernel: ipfw: 40 Reset TCP 192.168.226.253:26218 192.168.1.100:22 in via re0
Jun 5 22:53:18 mm kernel: ipfw: 40 Reset TCP 192.168.145.1:61878 192.168.1.100:22 in via re0
Jun 5 22:54:11 mm kernel: ipfw: 40 Reset TCP 192.168.98.253:42187 192.168.1.100:22 in via re0
Jun 5 22:54:58 mm kernel: ipfw: 40 Reset TCP 192.168.82.253:25475 192.168.1.100:22 in via re0
Jun 5 22:55:32 mm kernel: ipfw: 40 Reset TCP 192.168.146.253:37578 192.168.1.100:22 in via re0
对应的40规则是阻止所有连接ssh的包:
ipfw add 40 deny log logamount 80000 ip from any to me dst-port 22
在这个日志中,可以看到(1)时间;(2)对应的ipfw规则号;(3)协议;(4)源地址和端口;(5)目的地址和端口。
虽然几个信息对大多数情况来说足够用,但是如果想深入分析的话,还是远远不够的,比如想看一下数据包拆分的情况,tos,数据包里面的内容,这种方式就没有用了。
ipfw提供了虚拟网卡的方式,可以让你看到任何的细节,因为从使用的角度来说,它就是一个网卡,只不过通过这个网卡的数据是从ipfw的log规则里面转过来的:
root@test:/root # ifconfig ipfw0 create
root@test:/root # ipfw add 80 allow log logamount 80000 ip from any to me dst-port 80
root@test:/root # sysctl net.inet.ip.fw.verbose=0
root@test:/root # tcpdump -D
1.em0
2.ng0
3.ipfw0
4.em1
root@test:/root # tcpdump -ani ipfw0
tcpdump: WARNING: ipfw0: That device doesn't support promiscuous mode
(BIOCPROMISC: Invalid argument)
tcpdump: WARNING: ipfw0: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ipfw0, link-type EN10MB (Ethernet), capture size 65535 bytes
capability mode sandbox enabled
09:39:46.653210 53:53:53:53:53:53 > 44:44:44:44:44:44, ethertype IPv4 (0x0800), length 115: 101.28.208.118.80 > 192.168.1.100.80: UDP, length 73
0x0000: 4500 0065 6c92 0000 3911 9bcd 651c d076 E..el...9...e..v
0x0010: dd02 6693 0050 0050 0051 5c79 fe46 0000 ..f..P.P.Q\y.F..
0x0020: 4601 b002 0502 a040 d903 4800 008d 1881 F......@..H.....
0x0030: 09e7 aa1a 8cba b1ae deea dbeb 2a0a 6461 ............*.da
0x0040: b09b 574d e6b6 9c3d 3add ea1e dff3 c55a ..WM...=:......Z
0x0050: 032a d015 8e2c 107c 7884 ea38 7419 69f0 .*...,.|x..8t.i.
0x0060: 0147 149d fc .G...
09:39:56.718059 53:53:53:53:53:53 > 44:44:44:44:44:44, ethertype IPv4 (0x0800), length 475: 125.39.202.107.8000 > 221.2.102.147.80: UDP, length 433
……
当然你也可以使用-w参数,把tcpdump的内容记录到文件中去。
本文开始的问题:只能有ipfw0吗?答案是可以是任何数字,但是只能有一个:
root@test:/root # ifconfig ipfw1 create
ifconfig: SIOCIFCREATE2: File exists
root@test:/root # ifconfig ipfw0 destroy
root@test:/root # ifconfig ipfw1 create
root@test:/root # ifconfig ipfw1 destroy
root@test:/root # ifconfig ipfw2 destroy
ifconfig: interface ipfw2 does not exist
root@test:/root # ifconfig ipfw2 create
root@test:/root # ifconfig ipfw2 destroy
root@test:/root # ifconfig ipfw20 create
root@test:/root # ifconfig ipfw20
ipfw20: flags=8801<UP,SIMPLEX,MULTICAST> metric 0 mtu 65536
但是最大值能到327xx(难道FreeBSD只能支持到32768个网卡?):
root@test:/root # ifconfig ipfw65530 create
ifconfig: SIOCIFCREATE2: No space left on device
root@test:/root # ifconfig ipfw32768 create
ifconfig: SIOCIFCREATE2: No space left on device
root@test:/root # ifconfig ipfw16384 create
root@test:/root # ifconfig ipfw16384 destroy
root@test:/root # ifconfig ipfw32000 create
root@test:/root # ifconfig ipfw32000 destroy
root@test:/root # ifconfig ipfw32700 create
root@test:/root # ifconfig ipfw32700
ipfw32700: flags=8801<UP,SIMPLEX,MULTICAST> metric 0 mtu 65536
root@test:/root # ifconfig ipfw4096 create
root@test:/root # ifconfig ipfw4096 destroy