nftables: The Next Generation Firewall in Linux Tomofumi Hayashi @s1061123 第 11 第 第第第第 /VM 第第第
nftables: The Next Generation Firewall in Linux
Tomofumi Hayashi@s1061123
第 11 回 カーネル /VM 探検隊
Agenda
• 自己紹介• nftables について• nftables の使い方• nftables の読み方• nftables の書き方
• 宣伝• まとめ
Agenda
• 自己紹介• nftables について• nftables の使い方• nftables の読み方• nftables の書き方
• 宣伝• まとめ
自己紹介なまえ: はやしともふみtwitter: @s1061123
カーネル /VM 勉強会歴 : 5 年ぶり 2 度目の出場
とりあえずNotice:• この発表は個人の見解、また調査結果に基づくものであ
り、所属する組織、 nftables 開発チームの公式見解ではありません
• 幾つかの技術的資料についてはその出展をなるべく明記しています
• nftables を開発しているチームの方に感謝致します
http://s1061123.net/nft/
お詫び
? !
お詫び• LinuxCon とネタが被りました ww– 気付いたのは発表申し込みした後です…
• タイトルは意図的にダブらせました
お詫び• LinuxCon とネタが被りました ww– 気付いたのは発表申し込みした後です…
• タイトルは意図的にダブらせました
Fiirewall ?!
お詫び• LinuxCon とネタが被りました ww
– 気付いたのは発表申し込みした後です…• タイトルは意図的にダブらせました
• LinuxCon 怖いところ…っ !– こわいので LinuxCon には参加していません– 内容が LinuxCon とダブっていたら申し訳ありません– ↑ の内容知ってる人いらっしゃいましたら後で教えて下さ
い
• 知らないなりにカーネル /VM らしい発表をする方向で
そんなふうに考えていた時期が…俺にもありました…
? !
LinuxCon 前日のタイムテーブル
? !
お詫び• LinuxCon とネタが被りました ww せんでした
– 気付いたのは 2 日前です…• タイトルは意図的にダブらせました
• LinuxCon 怖いところ…っ !– こわいので LinuxCon には参加していません– 内容が LinuxCon とダブっていたら申し訳ありません– ↑ の内容知ってる人いらっしゃいましたら後で教えて下さ
い
• 知らないなりにカーネル /VM らしい発表をする方向で
Agenda
• 自己紹介• nftablesについて• nftables の使い方• nftables の読み方• nftables の書き方
• 宣伝• まとめ
nftables ってなに?http://netfilter.org/projects/nftables/
• nftables とは {ip,ip6,arp,eb}tables 関係の tool を新たに置き換えるプロジェクト
• {ip,ip6,arp,eb}tables 同様に netfilter を使っている
netfilter, iptables and nftables?• netfilter
– Linux にあるパケット書き換えのフレームワーク– NAT, NAPT, IP MASQUERADE 等を実装– conntrack も netfilter の機能
• iptables, ip6tables, ebtables and arptables– netfilter を使って実装したパケットフィルタリング コマンド– ‘-m udp’ のように必要な機能がコマンド・カーネルで拡張されている– fedora‘s ’firewalld‘ も実際呼んでるのはこのコマンド
• nftables <- これ !– パケットフィルタリングコマンド– iptables 等と同様に netfilter を使用している
netfilter, iptables and nftables?• netfilter
– Linux にあるパケット書き換えのフレームワーク– NAT, NAPT, IP MASQUERADE 等を実装– conntrack も netfilter の機能
• iptables, ip6tables, ebtables and arptables– netfilter を使って実装したパケットフィルタリング コマンド– ‘-m udp’ のように必要な機能がコマンド・カーネルで拡張されている– fedora‘s ’firewalld‘ も実際呼んでるのはこのコマンド
• nftables <- これ !– パケットフィルタリングコマンド– iptables 等と同様に netfilter を使用している
netfilter, iptables and nftables?
30 秒で分かる netfilter :netfilter は Linux 内でネットワークのパケットを書き換えることができます。以下のようにどこで呼ぶかを指定できるように hook が存在しますIn include/uapi/linux/netfilter.h:
enum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, NF_INET_NUMHOOKS};
netfilter, iptables and nftables?
なので、 hook を指定して自分の関数を登録すれば以下のようなカーネルがパケットを処理するタイミングでその関数が呼ばれることになりますnet/ipv4/ip_forward.c:
int ip_forward(struct sk_buff *skb){ u32 mtu; struct iphdr *iph; /* Our header */ struct rtable *rt; /* Route we use */ struct ip_options *opt = &(IPCB(skb)->opt); (snip) return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, rt->dst.dev, ip_forward_finish);sr_failed: (snip)}
SKB!!
netfilter, iptables and nftables?• netfilter
– Linux にあるパケット書き換えのフレームワーク– NAT, NAPT, IP MASQUERADE 等を実装– conntrack も netfilter の機能
• iptables, ip6tables, ebtables and arptables– netfilter を使って実装したパケットフィルタリング コマンド– ‘-m udp’ のように必要な機能がコマンド・カーネルで拡張されている– fedora‘s ’firewalld‘ も実際呼んでるのはこのコマンド
• nftables <- これ !– パケットフィルタリングコマンド– iptables 等と同様に netfilter を使用している
{ip,ip6,arp,eb}tables?
iptables は Linux でパケットをフィルタしたり、 NAT などでパケットを書き換えたりすることができるソフトです
Linux でホームルータを作る際には ( ほぼ ) 必須
iptables は以下のもので構成されています– iptables コマンド– カーネル側の (netfilter を呼ぶ )iptables 用コード
{ip,ip6,arp,eb}tables?
各種通信プロトコル・ネットワーク機能毎に以下のコマンドが存在します
• IPv4: iptables• IPv6: ip6tables• ARP: arptables
( ロードバランサ・ LVS/Linux Virtual Server 等で使用 )
• Bridge: ebtables( カーネルの Bridge 内で処理 )
netfilter, iptables and nftables?• netfilter
– Linux にあるパケット書き換えのフレームワーク– NAT, NAPT, IP MASQUERADE 等を実装– conntrack も netfilter の機能
• iptables, ip6tables, ebtables and arptables– netfilter を使って実装したパケットフィルタリング コマンド– ‘-m udp’ のように必要な機能がコマンド・カーネルで拡張されている– fedora‘s ’firewalld‘ も実際呼んでるのはこのコマンド
• nftables <- 今日はこれ !– パケットフィルタリングコマンド– iptables 等と同様に netfilter を使用している
nftables?
なんで nftables ?
• 技術的負債の解消• パフォーマンス向上
nftables?
iptables が持つ技術的負債• iptables が産まれたのは 1999 年 11 月– http://www.netfilter.org/about.html#history– 16 年経過 !
• Extension Modules の増加– 現在 70 個以上の Module が存在– それぞれカーネル側・ユーザランド側に存在
• プロトコル毎に別コマンド– 似たようなコードが各種コマンドに存在
• そもそもシンタックス・ルールが複雑化
nftables?
iptables が持つパフォーマンス問題• そもそもルールセット追加・削除が Atomic!• ルールの更新の際はそのルールを全部ユーザランドにコ
ピーして処理• ルールが増えればそれだけ処理が重くなる…
from http://www.slideshare.net/ennael/2013-kernel-recipesnftables
nftables!
技術的負債の解消やパフォーマンス向上を目的にして開発• 2008 年に Patrick McHardy 氏が開発• 2010 年に一回開発が止まったものの• 2012 年に Pablo Neira Ayuso 氏が iptables 互換レイヤーを開発
• 2014 年 1 月にカーネルメインライン (3.13) にマージ済
Agenda
• 自己紹介• nftables について• nftablesの使い方• nftables の読み方• nftables の書き方
• 宣伝• まとめ
nftables の使い方• カーネルに NF_TABLES( と好きな OPTION) を付けてビル
ド• ユーザ側のコマンドをビルド (Gentoo ならば net-
firewall/nftables を emerge)• iptables を使っている場合は iptables を止める
(モジュールのビルド・ロードだけならば大丈夫 )
• `service nftables start` 等でサービスを開始• `nft` コマンドでルールの追加・削除が可能
– `nft –f <filename>` でファイルからの読み込み– `nft –i` でインタラクティブモードnft_test ~ $ nft -i
nft> list tablestable nattable filternft>
nftables のシンタックス
% sudo iptables -t filter -S-P INPUT ACCEPT-P FORWARD ACCEPT-P OUTPUT ACCEPT-N ssh_whitelist-A INPUT -i lo -j ACCEPT-A INPUT -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN –j ssh_whitelist// (略 )-A ssh_whitelist -s 192.168.0.0/16 -j ACCEPT-A ssh_whitelist -s 10.0.0.0/8 -j ACCEPT-A ssh_whitelist -j DROP
nftables:# nft list table ip filtertable ip filter { chain input { type filter hook input priority 0; } chain forward { type filter hook forward priority 0; iif eth0 oif != eth0 jump miniupnpd drop } chain output { type filter hook output priority 0; } chain miniupnpd { iif eth0 ip daddr 192.168.1.10 tcp dport ssh accept }}
iptables:
nftables のシンタックス詳細は web で !
nftables のシンタックス詳細は web で !
nftables のシンタックス詳細は web で !
nftables のフローnft で入力されたコマンドは以下のパスを通ってカーネルに送られます
from https://www.netdev01.org/docs/nftables-rmll-2014.pdf
nftables のフローlibnftnl/examples/nft-rule-get でルールを見ると…
nftables のフローlibnftnl/examples/nft-rule-get でルールを見ると…
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
nftables のフローnft で入力されたコマンドは以下のパスを通ってカーネルに送られます
from https://www.netdev01.org/docs/nftables-rmll-2014.pdf
コンパイル?
nftables のフローnft で入力されたコマンドは以下のパスを通ってカーネルに送られます
from https://www.netdev01.org/docs/nftables-rmll-2014.pdf
コンパイル?
nftables (internal)
カーネル内の nftables のフィルタリング実装はpseudo-state machine として実装されています
• bpf (Berkeley Packet Filter) からインスパイア (*1原文ママ )– 4 registers– 1 verdict (e.g. 'accept', 'drop', 'jump' or so ...)– A extensive instruction set
reject, meta, masq, bitwise, byteorder, cmp, counter, ct (conntrack), exthdr, immediate, limit, log, lookup, nat, payload, queue(順不同、適当に検索 )
*1 http://www.slideshare.net/ennael/2013-kernel-recipesnftables
nftables (internal)
カーネル内の nftables のフィルタリング実装はpseudo-state machine として実装されています
= カーネル内の VM → カーネル /VM!!• bpf (Berkeley Packet Filter) からインスパイア (*1原文マ
マ )– 4 registers– 1 verdict (e.g. 'accept', 'drop', 'jump' or so ...)– A extensive instruction set
reject, meta, masq, bitwise, byteorder, cmp, counter, ct (conntrack), exthdr, immediate, limit, log, lookup, nat, payload, queue(順不同、適当に検索 )
*1 http://www.slideshare.net/ennael/2013-kernel-recipesnftables
Agenda
• 自己紹介• nftables について• nftables の使い方• nftablesの読み方• nftables の書き方
• 宣伝• まとめ
Agenda
• 自己紹介• nftables について• nftables の使い方• nftablesの内部の VMコードの読み方• nftables の書き方
• 宣伝• まとめ
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 // 7:handle, 6:position [ payload load 4b @ network header + 12 => reg 1 ]
ネットワークヘッダの 12byte (saddr) から 4byte ロードしてreg1 に [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
reg1 を 0x00ffffff でマスクして 0 で xor を reg1 に [ cmp eq reg 1 0x0001a8c0 ]
reg1 が 0x0001a8c0 と比較 (0x0001a8c0 => 192.168.1.0)もしマッチしないならばここでリターン
[ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
ip saddr 192.168.1.0/24
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ]
oif の ifindex値を reg1 に [ cmp eq reg 1 0x00000004 ]
reg1 と 0x4 を比較 [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
oif eth0
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ]
reg1 に 0x100000a を代入 (0x100000a = 10.0.0.1) [ nat snat ip addr_min reg 1 addr_max reg 1 ]
snat を行なう (source は reg1 に入っている値 )
snat 10.0.0.1
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
nftables の読み方libnftnl/examples/nft-rule-get
ip saddr 192.168.1.0/24 oif eth0 snat 10.0.0.1=>ip nat postrouting 7 6 [ payload load 4b @ network header + 12 => reg 1 ] [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] [ cmp eq reg 1 0x0001a8c0 ] [ meta load oif => reg 1 ] [ cmp eq reg 1 0x00000004 ] [ immediate reg 1 0x100000a ] [ nat snat ip addr_min reg 1 addr_max reg 1 ]
ね、簡単でしょ?
Agenda
• 自己紹介• nftables について• nftables の使い方• nftables の読み方• nftablesの書き方
• 宣伝• まとめ
Agenda
• 自己紹介• nftables について• nftables の使い方• nftables の読み方• nftablesの内部の VMコードの書き方
• 宣伝• まとめ
nftables にルールを書きたい !
libnftnl を使うことで nftables のルールを追加・削除することが可能です
• libnftnl/examples/* と libnftnl/tests/* を参考にすれば、ほらこの通り !
e = nft_rule_expr_alloc("nat"); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_TYPE, NFT_NAT_SNAT); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_FAMILY, AF_INET); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN, NFT_REG_1); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX, NFT_REG_1); nft_rule_add_expr(r, e);
[ immediate reg 1 0x100000a ][ nat snat ip addr_min reg 1 addr_max reg 1 ] =>
nftables にルールを書きたい !
libnftnl を使うことで nftables のルールを追加・削除することが可能です
• libnftnl/examples/* と libnftnl/tests/* を参考にすれば、ほらこの通り !
e = nft_rule_expr_alloc("nat"); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_TYPE, NFT_NAT_SNAT); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_FAMILY, AF_INET); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN, NFT_REG_1); nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX, NFT_REG_1); nft_rule_add_expr(r, e);
[ immediate reg 1 0x100000a ][ nat snat ip addr_min reg 1 addr_max reg 1 ] =>
nftables にルールを書きたい ! nl = mnl_socket_open(NETLINK_NETFILTER); if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); return -1; } } batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_BEGIN, seq++); mnl_nlmsg_batch_next(batch); nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), cmd, nft_rule_attr_get_u32(rule, NFT_RULE_ATTR_FAMILY), NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); nft_rule_nlmsg_build_payload(nlh, rule); nft_rule_free(rule); mnl_nlmsg_batch_next(batch);
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, seq++); mnl_nlmsg_batch_next(batch); ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); mnl_nlmsg_batch_stop(batch); ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
Netlink (libnml 等 ) でカーネルに送信 !!!
nftables にルールを書きたい ! nl = mnl_socket_open(NETLINK_NETFILTER); if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); return -1; } } batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_BEGIN, seq++); mnl_nlmsg_batch_next(batch); nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), cmd, nft_rule_attr_get_u32(rule, NFT_RULE_ATTR_FAMILY), NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, seq++); nft_rule_nlmsg_build_payload(nlh, rule); nft_rule_free(rule); mnl_nlmsg_batch_next(batch);
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, seq++); mnl_nlmsg_batch_next(batch); ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); mnl_nlmsg_batch_stop(batch); ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
ほら、簡単でしょ?
Netlink (libnml 等 ) でカーネルに送信 !!!
Agenda
• 自己紹介• nftables について• nftables の使い方• nftables の読み方• nftables の書き方
• 宣伝• まとめ
宣伝MiniUPnP が nftables をサポートすることになりました
– MiniUPnP は NAT の内側から forwarding の穴を簡単に開けることができる NAT 向けの機能 IGD の実装です
– 先月から github の current のコードに入っています
=> 「 UPnP が無いから…」と思う人も安心 !!
まとめさぁ、みんなも nftables で人柱になろう !!