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 tables
table nat
table filter
nft>
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 filter
table 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で人柱になろう!!
nftables: the Next Generation Firewall in Linux

nftables: the Next Generation Firewall in Linux