do_su_0805's blog

dairyquestions は typo です。

ghq look 廃止に伴う PS1 変更スクリプトを供養する

あとで Quyo | つづろう、モノの思い出 にも供養します

先日 ghqで仕事用と趣味用でディレクトリ分けしてリポジトリ管理しやすくなりました | おそらくはそれさえも平凡な日々 で発表されていましたが、ghq version 0.99.0 より、 ghq look コマンドが廃止となりました。

廃止の経緯などは上述の id:Songmu さんの記事に書かれていますが、僕もどちらかというと「普段使いに ghq look を使う」人間でした。 様々な「こうしたほうがいい」「王道」「回避策」などがありますが、ここではその辺りには触れずに、 ghq look 利用時に「 ghq look で開いたサブシェルかどうか」を判定していた方法を供養しておきます。

やってたこと

いたってシンプルなのですが、 ghq look で開かれたサブシェルの時は、環境変数 GHQ_LOOKghq.root 以下の移動先パスになります。 それを検知して、ghq look 配下時には PS1 先頭に [g] と出すようにしていました。

if [ "X${GHQ_LOOK}" != "X" ];then
  ghq_flag="[g]"
fi
PS1='\[\e[31;40m\]${ghq_flag}\[\e[m\]\[\e[36;40;4m\][bash] \u@\h:\W\[\e[m\]\[\e[31;40m\]$(__git_ps1 " (%s)") \[\e[m    \]\$ '

実際に使うとこんな感じ

[bash] do-su-0805@hostname:~ $ ghq get --look do-su-0805/repoA
    exists /Users/do-su-0805/.ghq/src/github.com/do-su-0805/repoA
[g][bash] do-su-0805@hostname:repoA (master) $

ある意味「サブシェルによって環境変数が引き継がれないこと」を便利に使っていたので、 ghq get --look を継続して使うかは悩みどころですが、まぁいい感じにしていきたいですね。

ちなみに

id:astj さんも同様のことをされていたらしいというのは調べていて見つけました。 対する id:Songmu さんの応答で ghq get --look で同等の動作をすることを知りました。

FAI が動く環境を構築して、Debian 9.8 install が自動でできるまで

TL;DR

  • Ubuntu 18.04.02 LTS 上に FAI をインストールした。
    • 一部、デフォルトの設定だと動かなかったので、環境に合わせた修正を実施した。
  • デフォルトで内包されている DebianGnome install が、PXE boot で自動的に完了することを確認した。
続きを読む

雑に nginx 1.15.9 の変更差分を眺めた

という tweet を見かけ、 nginx 1.15.9 の CHANGES を見てきた

Changes with nginx 1.15.9 26 Feb 2019

*) Feature: variables support in the "ssl_certificate" and "ssl_certificate_key" directives.

*) Feature: the "poll" method is now available on Windows when using Windows Vista or newer.

*) Bugfix: if the "select" method was used on Windows and an error occurred while establishing a backend connection, nginx waited for the connection establishment timeout to expire.

*) Bugfix: the "proxy_upload_rate" and "proxy_download_rate" directives in the stream module worked incorrectly when proxying UDP datagrams

  • ssl_certificatessl_certificate_key が変数対応した
  • poll 関数が windows vista 以降なら使えるようになった
  • select メソッドのバグフィックス
  • proxy_upload_rate / proxy_download_rate が、UDP で不完全に動いていたのを直した。

なるほどなぁと思いつつ、proxy_*_ratessl_cerificate なんたらについて気になったので、ソースコードを見てみようと思って、いい感じの diff にたどり着くまでのお話です。

ソースコードのありか

nginx のソースコードは、公式ページからたどると https://trac.nginx.org/nginx/browser にあるらしい。

また、これを一時間に一回同期している、 https://github.com/nginx/nginx というリポジトリもある

いい感じに github で diff を見たい

  • 下記に掲載されているように、 compare/(from)...(to) という方法で差分が見れるということらしい。 kanonji.hatenadiary.com

今回は、 release-1.15.8release-1.15.9 の差分を見ることにする - https://github.com/nginx/nginx/compare/release-1.15.8...release-1.15.9

雑に見てみた感想

ちゃんとコードを追ったりはしてないけど、ここら辺中心に見たらssl関連はいろいろ面白そうという勘だけおいておく。どっかで気が向いたら見る

  • 新設関数 or ifdef による挙動新設があるものうち、関係がありそうなもの
    • int ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
    • int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
    • ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords)
    • ngx_int_t ngx_http_test_required_predicates(ngx_http_request_t *r,ngx_array_t *predicates)
    • static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf,ngx_http_ssl_srv_conf_t *conf);
    • static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,ngx_stream_ssl_conf_t *conf)
    • static X509 *ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert, STACK_OF(X509) **chain)
    • static EVP_PKEY *ngx_ssl_load_certificate_key(ngx_pool_t *pool, char **err,ngx_str_t *key, ngx_array_t *passwords)
    • ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords)
  • ngx_ssl_certificate 関数の挙動
    • X509 の STACK_OF である *chain が表れて、 sk_X509_pop_free とかに突っ込まれている
  • nginx_ssl_session_* な関数の引数増加
    • ngx_ssl_session_cachengx_ssl_session_id_contexngx_array_t *certificates という今回の変更ど直球ぽい引数追加
  • ngx_http_request_t *ngx_http_create_request(ngx_connection_t *c) の挙動が新設され、以前の挙動が static ngx_http_request_t *ngx_http_alloc_request(ngx_connection_t *c) に一部移植されている
  • ngx_event_openssl.c まぁ名前的にしょうがないとはいえ、 #ifdef が広範囲に広がっており、読むのに注意がいる
  • 個人的に気になったのは、 ngx_freebsd_config.h に微妙な変更が入ってる。多分、ngx_file_aio_read.c の変更向け
    • FreeBSD_version < 700005 って、FreeBSD 7 か?

2月からやりたいこと

今年もよろしくお願いします。

新年入って、京都に引っ越して時間ができるようになりました。 また、転職後初の評価が終わり、新しい半期に入りました。

やっと引っ越しの片づけが落ち着いてきたので、改めて今考えているやりたいことをいったん書き出してみようという企画です。 手を動かさないとねという気持ちは最近強くなってきました。

ネットワーク設計

  • 出口は VRRP しておきたい。
    • メインは IX2105 + 光回線環境
      • 下りが遅い。上りはめちゃくちゃ早い
    • サブとして、 IX2005 + JCOM 回線環境
      • 上りが遅い。下りは結構早い
      • VRRP の対向として、1GbE の NVR500 があるけど、NEC / YAMAHA は怖い気もする
  • ローカルネットワークは 2 つか 3 つ切っておく
    • 1 つ目は一般的な機器。
    • 2 つ目はお客様
    • 3 つ目は仮想マシン類。一旦はサーバに NIC 増やすもの大変だし、置いておく。
      • 1 つ目に含めておく?かな。しばらくは。
      • これを実現するために、 VLAN を切るというのもありかなぁ。

サーバについて

  • 現状スペック
    • i7-3770k / 32GB ME
  • 最低限必要なサーバ
    • syslog サーバ あるいはこれに準ずるもの
  • それ以外は遊び場になる
    • ディスク構成が結構不安な状況なので、いろいろ考えよう
      • 160GB 単発がシステムディスク
      • 320GB * 2(Linux md) で、lvm 運用してる
      • システムディスク死なれると悲しい + 仮想ホストだしこっち安めの SSD でも探そうかな
        • M.2 SSD と 256GB SSD 買ってくれば、デスクトップから 256GB SSD 引きはがして交換できなくはない
      • データディスクは基本領域用は 320GB * 2 のままでもいい気がする
        • または 1本にして、1本はバックアップを別途とるようにするか
      • 追加で大容量データ用に 1TB か、デスクトップに刺さってる 500GB をいい加減掃除して持っていくか

やりたいこと

プロビジョニングツールの上達/習得

  • chef / ansible

xen 環境の操作

  • KVM はもう一台足せたら考える

仮想マシンポコポコ立てていろいろ試す

  • 実はデスクトップが 16thread / 32GB MEMなので、こっちにも建てられるけど、寝るときはデスク消したい
    • こっちは、遊ぶ時の手元環境として一台くらい VirtualBox / VMware / Hyper-V かな…
    • 一瞬、Linux メイン / グラボを PCIe パススルーして仮想マシンwindows も考えたけど、結局寝るとき消したいので利点があまりない
  • ノートパソコンも T450s で、 i7-4600U?(なのか?忘れた) / 20GB MEM なので建てられるけど、また違う…
    • こっちは「いろいろできなくもない」とかの想定でメモリガン積み中古ノートにした
  • 試したいことの概要
    • DB いろいろ試したい
    • Web アプリケーション
      • わからないことがわかってきた(無知の知

まずやること

  • 出口が気になっていることから、ネットワークをどうにかしよう
    • お客様もすぐにはいらない。とりあえず出口のことを考えよう
    • syslog はどうする?すぐにはいいか。

whywaita さんはどこにでもいるよ

この記事は、whywaita Advent Calendar 2018 - Adventar20日目の記事です。

初めましての方は初めまして。 id:do_su_0805 と申します。

whywaita さんとは直接話した機会は片手程度な気がする仲ではありますが、気づくと「知人の知人が whywaita 」というケースであったり、場合によっては同組織に所属していた期間があったりと世間は狭いなぁというお話をさせてください。1

なお、この記事を書くにあたって、結果的にこのエントリーを出す前に転職エントリを執筆する必要が出てきたため、先行で公開しております。

転職エントリ - do_su_0805's blog

自己紹介

改めまして初めまして。 id:do_su_0805 と申します。

簡単に経歴を紹介させていただくと、

という経歴を辿ってきたものです。

kosen10s という、「2010年度に高専に入学した人たちのコミュ二ティ」に所属しています。

whywaita さんとの繋がり

whywaita さんとのパス その1 ICTトラブルシューティングコンテスト

直接の関わりはなかったのですが、私自身、ICTトラブルシューティングコンテストというイベントの運営学生だったことがあります。
前職の同期がもともと初代優勝者、2回目以降ずっと運営に携わっておられる方で、「参加してみない?」とお声掛けをいただき、参加しました。
なお、ネットワーク機器の設定なんてあまりやったこともなかった人間だったため、最後は人間redmineアサイン機になったりしていました。ご迷惑をおかけいたしました・・・。

どうやらその次の 第四回 から whywaita さんは継続的に運営に参加されておられます。
この記事で「運営に誘ってくれた」とある id:jackson58 や、「技術的な支援をしてくださった」とある id:kuro_m88 とかと一緒に運営委員をやっていました。
世間は狭いです。

whywaita さんとのパス その2 電気通信大学

kosen10s 関連などで電気通信大学に友人が何名かいます。2
また、 whywaita 氏も電気通信大学に所属しておられます。
まぁかち合わないわけがなく、twitter などで何度もお見受けし、初めて存在を認識したのがこの辺りだと思います。

whywaita さんとのパス その3 kosen10s

これもう、後述の #5 の時は理解が追いつかなかったんですが、whywaita 氏は kosen10s のイベント、 kosen10s LT #5#12 などに参加されています。
自他共に認める「準高専生」という称号があり、これもまたすごいなぁと思いました。 確かにシンパシーを感じる瞬間は多々あります。 この辺りから、「世間って狭いなぁ」と思い始めました。

whywaita さんとのパス その4 前職

先ほど転職エントリをあげさせていただきましたが、つい4ヶ月くらい前までさくらインターネット株式会社に所属しておりました。
自身が twitter に挙げられていたので引用させていただきますが、

というわけで、whywaita 氏もさくらインターネット株式会社でアルバイトとして就業しておられ、勤続的に重なった期間が少なからずあります。
ここはもう完全に「世間って(ry)」となりましたが、気づいた頃から彼が僕の分報チャンネルにいた気がします。3

whywaita さんとのパス その5 現職

同じく先ほど転職エントリにて触れましたが、現在株式会社はてなに所属しています。
まず入社直後からメンターをしてもらってる方が、「whywaita とは同じアルバイト先だったよ」と話になり驚き、
この AdventCalendar を毎年作成されている id:masawada さんなども同僚になりました。そういえば初対面の話は whywaita さんのお話でした。
いやはや、whywaita 氏どこでも知り合いがいてすごいなぁと本当に思いました。

最後に

ISUCON8 優勝おめでとうございます!
これからもご活躍を草むらの陰から追っていけたらと思います。 改めてどうぞよろしくお願いいたします!


  1. きっとみなさんも多いと思うのですが・・・ひとえに whywaita さんの活動範囲の広さの賜物と思っており、尊敬しています。

  2. 何かプレゼンテーションかの授業で、kosen10s のメンバーが僕の自己紹介スライドを作っていた(?)らしく、先ほどの「運営に誘ってくれた」方が驚いていたのを覚えています。 (https://twitter.com/staybuzz/status/598498171484966912)

  3. ひとりごとうるさくてごめんね

転職エントリ

学生時代から在職中、転職活動中にお世話になったみなさまありがとうございました。
これからもどうぞよろしくお願いいたします。

iptables-extentions に含まれる u32 についてのご紹介

追記 2022/04/06

この内容についてスライドも作りました。

speakerdeck.com

TL;DR

  • TL;DRとは
  • この記事は #kosen10s Advent Calendar 2018 - Adventar の 17日目の記事です。遅刻して申し訳ございません。
    • 昨日の記事は、 id:satuma77 さんで、「掴んで見せます!自分星!」とのことでした。comming soon ってやつですね。
    • 明日の記事は id:denari01 さんです。今のところすべての advent calendar に未投稿の様子です。お忙しいんでしょうね…。
    • 毎年、技術っぽい記事とそうでない生活の知恵的な記事を書いているので、これは前者側の記事です。後者側については 9日目の 転職活動まとめ - do_su_0805's blog でした。
  • 昔、ちょっと調べた iptables の u32 というオプションでどんなことができるのか、というのを例を交えてご紹介します。
    • ちなみに「これ見たことがあるぞ!」という人がいるかもですが、記憶を頼りに調べなおして見た感じです。
  • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x01" -A INPUT -j DROP すれば icmp_seq が偶数のときだけ通って、
    iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x00" -A INPUT -j DROP すれば icmp_seq が奇数のときだけ ping が通るような不思議サーバができます、
    という話をパケットの仕組みを交えながら解説します。

前書き

iptables を使うと、いろいろな通信について、カウント(ロギング)や許可、排除などができます。
(実を言うと iptables 自体に慣れ親しんでいるわけでもないので、どこまでできるのか、というのは詳しくはありません。 )
ですが、そんな iptables でも手が届かない場所ってのはあって、そんなケースにおいてもパケット自体を解析してルール化できるのが iptables u32 です。

今回は下記実例をもとに、紹介できればと思います。
なお、軽くは紹介しますが、この記事を読むに当たって、 IPヘッダの図ICMPヘッダの図 と、 TCPヘッダの図 を片手に読まれるとスムーズに読めると思います。

想定できる利用用途

といってもそんなに想定できません。
逆に、変なときにこれを知っていると実現できるかも、みたいなケースがあるかもしれません。
詳しいことは忘れて、存在だけ覚えておくといいかもしれないです。
パケットの構造さえ理解できれば、様々な種類のパケットに対応できるので、使い方は無限大だと思います。

共通お作法

使い方

  • iptables -m u32 --u32 まではお約束になります。
  • それ以降は、パケットの気持ちになってスタート位置を変えたり、シフト演算したり、アンド演算したりして、自分のほしい条件を作っていきます。
  • 末尾に iptables っぽい条件を追加することで、該当ルールとして作動させることができます。

実例

今回は、二つのケースを用意しました。

  • 対向から ping を飛ばし、 2 回に 1 回 受ける側で drop する
  • 対向から curl をずっとし続けて、 シーケンス 番号が偶数のものを drop する。

1. 対向から ping を飛ばし、 2 回に 1 回 drop する についての解説

先にルールを書いて、そこから解説していきます。

  • 偶数だけ通る
    • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x01" -A INPUT -j DROP
  • 奇数だけ通る
    • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x00" -A INPUT -j DROP
  • 自ホストの応答 output でやる場合
    • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x00 && 0>>22&0x3C@6>>16&0x01=0x01" -A OUTPUT -j DROP
    • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x00 && 0>>22&0x3C@6>>16&0x01=0x00" -A OUTPUT -j DROP

確認方法

  • ホスト A から、 ping を ホスト B に対して打ち続け、意図したとおりの状況になることを確認する

ルール解説

6&0xFF=0x1 について

iptables の u32 が解析するのは IP ヘッダからになります。
まずは、IPヘッダのプロトコル番号から、ICMP パケットかどうかを調べます。
プロトコル番号一覧 - Wikipedia を参考に、ICMP の場合は、 1 であることがわかりました。

u32 では、0 を IPヘッダの先頭とし、1バイトずつスタート地点をずらし、指定した起点から4バイトを読み込むことができます。
プロトコル自体は、IPヘッダの先頭から10バイト目にあります。 そのため、 6 を指定し、 7 ~ 10 バイト目を読み込みます。
また、読み込んだ 4byte は、1つの4byte列として処理を行います。(これを1オクテットと呼びます)

例として ping を受ける側で tcpdump -x してみたところ、4000 4001(16進数) がターゲットに入りました。

  • 先頭 3bit がフラグにあたり、010 であることがわかります。
  • そこからの 4bit ~ 16bit までの 13 ビットがフラグメントオフセットで、 0 であることがわかります。
  • きりが良くなり 3byte 目がTTLで、0x40 であることがわかります。
  • 最後の 1byte がプロトコルになり、0x01 であることがわかります。

ここで、判定したい情報は最後の 1byte の 0x01 であるため、 0xFF で AND マスクを行います。すると、4byte に格納された情報は、0x00000001 に変わります
これが 6&0xFF までの処理で、あとはその値が 0x1 と等しいかを比較したいので、6&0xFF=0x1 となりました。

&& 0>>22&0x3C@0>>24=0x08 または 0>>22&0x3C@0>>24=0x00 について

さっきまでの内容で、とりあえず ICMP パケットだけを絞り込むことができました。
と言っても、ICMP は利用範囲が大きいので、 echo-reply のみに絞れる方法を探します。
ここでは、ICMP パケットのタイプを利用します。

  • ICMP の タイプが 8 なら echo-request となるため、ここで範囲を絞ります。
    • なお、応用として、 echo-reply で弾く場合は、ここを 0 と考えて、OUTPUT に仕込みます

さっきまでの処理は IP パケットの中身で行っていましたが、今度は IP パケットの先にある、ICMP パケットに踏み込まなければなりません。
しかし、IPパケットには、「オプション」というフィールドが存在し、可変長として定義されています。
そのため、なんとかして、「IPパケットのサイズを知って、その先に踏み込む」処理が必要です。

では、IPパケットの構造に戻ります。実は IP パケットの先頭 1byte の後半 4bit に、「ヘッダ長」というエリアがあります。
例として取得してみると、先頭 4byte が 4500 0054 でした。これだと、どうやらヘッダ長は 5 みたいです。
しかし、ヘッダ長は、「オクテット数」を記録しており、5オクテット、つまり 20byte 目までは IP ヘッダであることを指します。
先程の話で、 6 で 7 byte 目まで移動できると説明しました。つまり次はここに、 20 を投入できれば今回のケースでの 21byte目、つまり ICMP ヘッダに踏み込むことができます。
しかしながら、現在、0x45000054 という列を相手にしているため、現状だとマスキングするだけでは、 0x05000000 という馬鹿でかいものが手に入ってしまい、うまく使えなそうです。
ここで、シフト演算が登場します。 今回の例だと、 0>>24 みたいにすると、0x00000045 にデータ加工することができます。しかしこれではほしい 20 は手にはいりません。
ここで 20 を入手するためのちょっとしたテクニックなんですが、シフト演算の性質を利用して、 0>>24 せずに、 0>>22 することで、最初から ヘッダ長に 4 をかけられた状態を情報を入手しています。
しかし、そのままだと 「サービス種別」の先頭 2bit が紛れ込んでいるため、 &0x3C することでマスキングしています。

  • 0x3C は、 0b00111100 となり、中途半端にシフトされた 4bit からほしい真ん中だけを抜き出すことができます。

解説にここの処理についてはイメージを作りました。

f:id:do_su_0805:20181218072607p:plain
IPヘッダの先頭4byteイメージ

f:id:do_su_0805:20181218072612p:plain
>>22 したあとのイメージ

f:id:do_su_0805:20181218072754p:plain
&0x3C したイメージ

こうすることで、実質 && 20 から始まりそうなんですが、これだとまだ 20 という数値が手に入っただけで、移動できていません。

続いて、 @0 というのが出てきました。これは先程触れた、移動をしてくれる記号です。
@ のあとについている 0 は初期条件同様、移動先から何byte 目から読み出すかを示します。
今回はICMPパケットの先頭 4byte を読みたいので、0 から読み出すことにします。

これでやっと ICMP パケットに踏み出すことに成功しました。取得したパケット例では、 0800 eaea が記録されていました。

  • 先頭 1byte がタイプにあたり、今回は 0x08 であることがわかります。
  • 次の 1byte がコードにあたり、今回は 0x00 であることがわかります。
  • 最後の 2byte がチェックサムにあたり、今回は、 0xeaea に当たります。

ここから、欲しい情報である先頭 1byte を抜き出すために >>24 します。すると、 0x08 のみがやっと手に入りました。
ここで、ping の受け手の INPUT 時であれば、8 が入っているはずなので、 =0x08 で比較します。

  • これを、一旦 ping の Echo Request 自体は受けて、返答時に落とすという変わった方法を取る場合は、 ここが 0 になるため、 =0x00 で比較します。

ここまでの条件を使うと、ICMP の Echo Request をすべて落とすことができます。

  • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08" -A INPUT -j DROP すると、外からの ping はすべて落ちると思います。

0>>22&0x3C@6>>16&0x01=0x01

  • ここで混乱を招かないように解説ですが、 && で繋いだあとはスタート地点が最初の 0 に戻ります。

続いて、「奇数のときだけ落とす」を実現するためにICMPパケットを更に深堀します。

0>>22&0x3C@ までは先程と同様で、IPヘッダから IPヘッダサイズを取得して移動しています。
しかし、今回は、 @6 になります。これは、Echo Message / Echo Reply Message 時に利用される、「シーケンス番号」が 7byte - 8byte 目に含まれるためです。
@6 することで、 7byte ~ 10byte までの 4byte が手にはいります。これが 0>>22&0x3C@6 までのハイライトです。
ここから、シーケンス番号が先頭2byte にあるため、一気に >>16 で前半 2byte のみにします。
あとは、奇数かどうかを判定するだけなので、末尾 1bit が 1 かどうかを調べるので、 &0x01 でマスキングして、 0x01 かどうかを比較すれば終わります。
あとはお好きな CHAIN に、お好きなルールで投入してみてください。

動作確認結果

対向から ping を 10 発打って結果を確認しました。
下記に2パターンの結果を載せていますが、正常に動作していそうです。

  • 地味に奇数のみ許可時に 50% packet loss を表示させるのが難しい。素直にカウント指定を入れればよかったけど、勘でいい感じに成功しました。

偶数のみ許可時

  • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x01" -A INPUT -j DROP した状態です。
do-su-0805@ubuntu01:~$ ping 192.168.1.7
PING 192.168.1.7 (192.168.1.7) 56(84) bytes of data.
64 bytes from 192.168.1.7: icmp_seq=2 ttl=64 time=0.329 ms
64 bytes from 192.168.1.7: icmp_seq=4 ttl=64 time=0.325 ms
64 bytes from 192.168.1.7: icmp_seq=6 ttl=64 time=0.311 ms
64 bytes from 192.168.1.7: icmp_seq=8 ttl=64 time=0.320 ms
64 bytes from 192.168.1.7: icmp_seq=10 ttl=64 time=0.317 ms
^C
--- 192.168.1.7 ping statistics ---
10 packets transmitted, 5 received, 50% packet loss, time 9210ms
rtt min/avg/max/mdev = 0.311/0.320/0.329/0.017 ms

奇数のみ許可時

  • iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08 && 0>>22&0x3C@6>>16&0x01=0x00" -A INPUT -j DROP した状態です
do-su-0805@ubuntu01:~$ ping 192.168.1.7
PING 192.168.1.7 (192.168.1.7) 56(84) bytes of data.
64 bytes from 192.168.1.7: icmp_seq=1 ttl=64 time=0.357 ms
64 bytes from 192.168.1.7: icmp_seq=3 ttl=64 time=0.367 ms
64 bytes from 192.168.1.7: icmp_seq=5 ttl=64 time=0.376 ms
64 bytes from 192.168.1.7: icmp_seq=7 ttl=64 time=0.379 ms
64 bytes from 192.168.1.7: icmp_seq=9 ttl=64 time=0.372 ms

--- 192.168.1.7 ping statistics ---
10 packets transmitted, 5 received, 50% packet loss, time 9209ms
rtt min/avg/max/mdev = 0.357/0.370/0.379/0.014 ms

2. 対向から curl をずっとし続けて、 ack 番号が偶数のものを drop する。

  • iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4&0x01=0x01" -A INPUT -j DROP
    • ルール自体は先程とだいたい類似するので、違うポイントを中心に紹介します。

実施方法

  • ホスト A から、 while で ホストB:80 に対して curl を 10発行い、実行ステータスを確認する。
    • この時、ホスト A で、tcpdump を取る

ルール考察

6&0xFF=0x6

先ほどと同じで、プロトコルを抜き出しています。これが ICMP では 1 でしたが、 TCP だと 6 になります。

0>>22&0x3C@4&0x01=0x01

先ほどと同じで、まずは IP ヘッダ長を取得し、ジャンプしています。
次に @4 しているのは、 TCP ヘッダの 5byte - 8byte が「シーケンス番号」のためです。
あとは &0x01 することで奇数偶数判定をしています。

結果

  • curl を 10発打って、ステータスコードで確認
    • 7 なら成功。28 なら失敗
    • for i in $(seq 1 10); do curl -s (target IP) --connect-timeout 1 || echo $?; done しました。
  • INPUT / OUTPUT 側で tcpdump で確認する。

    • なお、tcpdump のほうが先にパケットが通るため、後ほど iptables で弾こうが受け手側サーバでも確認はできる
    • 送信元の場合、 sudo tcpdump -v -vv tcp and dst (target IP) 2>&1 >> log & してから、ログをゴネゴネ
    • 受信元の場合、 sudo tcpdump tcp and src (source IP) 2>&1 >> log & してから、ログをゴネゴネ
      • (冗談みたいな話ですが、これやるとき tcpdump してればええやろーとルール投下後に ssh したら通らなくてそりゃ偶数弾くんだから確率で ssh も通らないわな・・・という自体が起きました。)
    番目 curl ステータス seq 番号
    1 7 228203506
    2 7 191816870
    3 28 1557318979
    4 28 3760951153
    5 28 3916607363
    6 28 2103122571
    7 7 3380433540
    8 28 4142152097
    9 7 2372256056
    10 7 1925275216
  • ちゃんと偶数のときだけ curl が成功していることがわかります。(ステータスが 7 なのはそもそも http サーバ立ててないからです・・・)

終わりに

いかがでしたでしょうか。そもそもが複雑というのと、うまい感じに表などが使えず分かりづらかったかもしれませんが、こういう機能もあるよ、と知っていただければ幸いです。