Archive for the ‘Linux’ Category

iptablesのログフォーマットと内容について

iptablesで -j LOG でsyslogに出力した時のそれぞれのフィールドについてわからないことが多かったので調べました。
どこにも詳しい説明がなかったので、最終的にLinuxのカーネルソースで確認しました。
kernel versionは、2.6.34.13 で確認しています。
net/ipv4/netfilter/ipt_LOG.c で生成しています。

今回は –log-ip-options , –log-tcp-options をつけたものについては省略してます。
(ソース見れば書いてあるのでわかるだろうってことで)

Oct 30 12:34:56 hoge kernel: [xxxxx.xxxxx] IPTLOG_FW : IN=eth1 OUT=eth0 MAC=aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:08:00 SRC=192.168.201.1 DST=172.16.101.30 LEN=118 TOS=0x00 PREC=0x00 TTL=254 ID=3120 DF PROTO=TCP SPT=3300 DPT=80 WINDOW=1460 RES=0x00 ACK PSH URGP=0

4つのパートにわかれています。

一番目

Oct 30 12:34:56 hoge kernel: [xxxxx.xxxxx] IPTLOG_FW :

syslogの先頭領域(共通)。
‘IPTLOG_FW’ の部分は、iptablesの引数 –log-prefix で指定できます。

二番目

IN=eth1 OUT=eth0 MAC=aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:08:00

MACレイヤ(L2)。
MACアドレスは先頭6octetがethポート(つまり、宛先の)MACアドレス、次の6octetが送信元MACアドレス、次の2octetはイーサネットタイプです。IPの場合0800になります(RFC1340のpage 53「ETHERNET NUMBERS OF INTEREST」に記載あり)。
この値は、skb_mac_header ( ) が返したものをそのまま出しています。

include/linux/skbuff.h

#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif

struct sk_buff {
   /* 中略 */
        sk_buff_data_t          mac_header;
   /* 中略 */
        unsigned char           *head,
}

static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
        return skb->head + skb->mac_header;
}

参考:連載:詳説 TCP/IPプロトコル 第7回 イーサネット(その2) イーサネットのフレーム構造 — 3.イーサネットのフレーム・フォーマット

三番目

SRC=192.168.201.1 DST=172.16.101.30 LEN=118 TOS=0x00 PREC=0x00 TTL=254 ID=3120 DF PROTO=TCP

IPレイヤ(L3)。
IPについては詳しくはRFC791を参照されたし。

  • SRC : ソースIPアドレス
  • DST : デスティネーションIPアドレス
  • LEN : IPパケット長
  • TOS : IPヘッダ TOSフィールドの値
  • PREC : IPヘッダ TOSフィールド内、PRECEDENCEの値
  • TTL : IPヘッダ TTLの値
  • ID : IPヘッダ IDの値
  • DF : IPヘッダ Flag の DFビット(Don’t Fragment)が立っている場合
  • PROTO : プロトコル(TCP,UDPなど)

該当ソースは下記のようになっております。(後半、省略してます)

        /* Important fields:
         * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
        /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
        printk("SRC=%pI4 DST=%pI4 ",
               &ih->saddr, &ih->daddr);

        /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
        printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
               ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
               ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));

        /* Max length: 6 "CE DF MF " */
        if (ntohs(ih->frag_off) & IP_CE)
                printk("CE ");
        if (ntohs(ih->frag_off) & IP_DF)
                printk("DF ");
        if (ntohs(ih->frag_off) & IP_MF)
                printk("MF ");

四番目

SPT=3300 DPT=80 WINDOW=1460 RES=0x00 ACK PSH URGP=0

TCPレイヤ(L4)。
TCPについては詳しくはRFC793を参照されたし。

  • SPT : ソースポート番号
  • DPT : デスティネーションポート番号
  • WINDOW : TCP Window
  • RES : Reservedの値
  • ACK , PSH , RST , SYN . FIN : Control Bitsのそれぞれに対応
  • URGP : Urgent Pointerの値

該当箇所のソースは下記の通りになってます。(一部省略)

                /* Max length: 20 "SPT=65535 DPT=65535 " */
                printk("SPT=%u DPT=%u ",
                       ntohs(th->source), ntohs(th->dest));
/* 中略 */
                /* Max length: 13 "WINDOW=65535 " */
                printk("WINDOW=%u ", ntohs(th->window));
                /* Max length: 9 "RES=0x3F " */
                printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
                /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
                if (th->cwr)
                        printk("CWR ");
                if (th->ece)
                        printk("ECE ");
                if (th->urg)
                        printk("URG ");
                if (th->ack)
                        printk("ACK ");
                if (th->psh)
                        printk("PSH ");
                if (th->rst)
                        printk("RST ");
                if (th->syn)
                        printk("SYN ");
                if (th->fin)
                        printk("FIN ");
                /* Max length: 11 "URGP=65535 " */
                printk("URGP=%u ", ntohs(th->urg_ptr));