- from: さくらインターネット株式会社 (2015年04月〜2018年08月)
- to: 株式会社はてな (2018年9月〜)
学生時代から在職中、転職活動中にお世話になったみなさまありがとうございました。
これからもどうぞよろしくお願いいたします。
学生時代から在職中、転職活動中にお世話になったみなさまありがとうございました。
これからもどうぞよろしくお願いいたします。
この内容についてスライドも作りました。
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 -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
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
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進数) がターゲットに入りました。
010
であることがわかります。0x40
であることがわかります。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 パケットのタイプを利用します。
さっきまでの処理は 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 からほしい真ん中だけを抜き出すことができます。解説にここの処理についてはイメージを作りました。
こうすることで、実質 && 20
から始まりそうなんですが、これだとまだ 20 という数値が手に入っただけで、移動できていません。
続いて、 @0
というのが出てきました。これは先程触れた、移動をしてくれる記号です。
@
のあとについている 0
は初期条件同様、移動先から何byte 目から読み出すかを示します。
今回はICMPパケットの先頭 4byte を読みたいので、0 から読み出すことにします。
これでやっと ICMP パケットに踏み出すことに成功しました。取得したパケット例では、 0800 eaea
が記録されていました。
0x08
であることがわかります。0x00
であることがわかります。0xeaea
に当たります。ここから、欲しい情報である先頭 1byte を抜き出すために >>24
します。すると、 0x08
のみがやっと手に入りました。
ここで、ping の受け手の INPUT 時であれば、8 が入っているはずなので、 =0x08
で比較します。
=0x00
で比較します。ここまでの条件を使うと、ICMP の Echo Request をすべて落とすことができます。
iptables -m u32 --u32 "6&0xFF=0x1 && 0>>22&0x3C@0>>24=0x08" -A INPUT -j DROP
すると、外からの ping はすべて落ちると思います。&&
で繋いだあとはスタート地点が最初の 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
iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4&0x01=0x01" -A INPUT -j DROP
6&0xFF=0x6
先ほどと同じで、プロトコルを抜き出しています。これが ICMP では 1 でしたが、 TCP だと 6 になります。
0>>22&0x3C@4&0x01=0x01
先ほどと同じで、まずは IP ヘッダ長を取得し、ジャンプしています。
次に @4
しているのは、 TCP ヘッダの 5byte - 8byte が「シーケンス番号」のためです。
あとは &0x01
することで奇数偶数判定をしています。
for i in $(seq 1 10); do curl -s (target IP) --connect-timeout 1 || echo $?; done
しました。INPUT / OUTPUT 側で tcpdump で確認する。
sudo tcpdump -v -vv tcp and dst (target IP) 2>&1 >> log &
してから、ログをゴネゴネsudo tcpdump tcp and src (source IP) 2>&1 >> log &
してから、ログをゴネゴネ
番目 | 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 サーバ立ててないからです・・・)
いかがでしたでしょうか。そもそもが複雑というのと、うまい感じに表などが使えず分かりづらかったかもしれませんが、こういう機能もあるよ、と知っていただければ幸いです。
@東京
とあるのは、東京への移動が発生しているケースです。
職務経歴詳細
職務要約より詳細に、実際にどんなことをしていたのか、みたいなのを期間と合わせて記載していきました。
期間 | 主な職務内容 |
---|---|
2015/07 - 2015/12 | hogehoge |
2016/01 - 2017/08 | fugafuga |
2017/09 - 現在 | fizzbuzz |
語学・実務経験
大きく分けて、下記三種類が選べる気がします。
そもそも住民税というのは、年間で支払う額が決まっていており、それを分割して天引きされています。
僕の場合は、次の会社で引き続き天引きしてもらうという方法になりました。
そのほかとしては、「最後の給与から来年5月分まで一括で納付」「自分で納付する」が選べそうでした。
GS108Ev3 というスイッチで検証をしています。
VLANID \ PORT | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
1 | T | U | T | - | - | U | T | T |
2 | T | - | - | U | T | - | - | T |
Port | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
PVID | 1 | 1 | 2 | 2 | 2 | 1 | 1 | 1 |
お久しぶりです。
題目の通り、Kosen10s LT#13 に行って、
珍しくちゃんと発表してきました。
今回は参加者20名(19名現地 + 1名リモート参加(!)) という結構集まったかな?という感じで、わいわいできました。
初参加の方も3名いらっしゃっていただき、これまた新鮮な会だったのでは?と思います。
発表資料は下のほうにも speakerdeck で公開していますが、あらかじめ見れるようにここにも貼っておきます。
speakerdeck.com
知らない人向けなざっくり Kosen10s って何?ということを説明すると、2010 年に高専に入学した全国の高専生(情報系が多いかな?) が slack でわいわいしたり交流したり、時には相談しあったり、こうやってLT会でわいわいしたりしている団体です。
2010 年に高専に入学した というのがミソで、中退/留年などは特に考慮していません。あくまでこのタイミングで入学したというポイントがそろっている集まりで、社会人も学生もいるし、いろんな人たちがいます。
故あって slack に入れる方法は今は公開されてないので、興味持たれた方はお声掛けいただくか、お近くの kosen10s っぽい人にお声掛けいただければ幸いです。
詳しくは、下記 Advent Calendar や、#kosen10s の日々のしょうもない日常について. - なっちゃんのめもがき。 などが参考になると思います。
ちなみに今年もアドベントカレンダーがあります!!
続きを読む2018/09/27 付の公開で、こんな記事が出ました。
https://aws.amazon.com/jp/about-aws/whats-new/2018/09/amazon-rds-postgresql-now-supports-iam-authentication/
Amazon RDS の PostgreSQL インスタンスで、IAM 認証ができるようになったみたいです。
早速試してみました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html
rds-db
な点、 dbuser
な点に注意しつつ作成しましょう{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "rds-db:connect" ], "Resource": [ "arn:aws:rds-db:リージョン:アカウント(数字):dbuser:リソース ID/ユーザ名" ] } ] }
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.DBAccounts.html
$ psql -h YOUR_INSTANCE_HOSTNAME -U masteruser -d testdb ユーザー masteruser のパスワード: psql (10.5 (Ubuntu 10.5-1.pgdg16.04+1)、サーバー 10.4) SSL 接続 (プロトコル: TLSv1.2、暗号化方式: ECDHE-RSA-AES256-GCM-SHA384、ビット長: 256、圧縮: オフ) "help" でヘルプを表示します。 testdb=> CREATE USER "testdb1003" WITH LOGIN; CREATE ROLE testdb=> GRANT rds_iam TO "testdb1003"; GRANT ROLE
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.AWSCLI.PostgreSQL.html - 上記がマニュアルですが、サンプルに誤りがあります。後述の手順では修正していますが、
export PGPASSWORD="$(aws rds generated-db-auth-token --hostname $RDSHOST --port 3306 --region us-west-2 --username jane_doe )"
とあるところの、 generated-db-auth-token
は、 generate-db-auth-token
が正しいです。ご注意ください。
$ export RDSHOST=YOUR_INSTANCE_HOSTNAME $ aws rds generate-db-auth-token --hostname ${RDSHOST} --port 5432 --region ap-northeast-1 --username testdb1003 --profile test
すると、こんな感じの文字列が表示されます。されずに aws cli のエラーなどが出たら適宜見直してください
YOUR_INSTANCE_HOSTNAME:5432/?Action=connect&DBUser=testdb1003....(中略) $
$ export PGPASSWORD="$(aws rds generate-db-auth-token --hostname ${RDSHOST} --port 5432 --region ap-northeast-1 --username testdb1003 --profile test)" $ psql "host=${RDSHOST} port=5432 sslmode=verify-full sslrootcert=/path/to/rds-combined-ca-bundle.pem dbname=testdb user=testdb1003" psql (10.5 (Ubuntu 10.5-1.pgdg16.04+1)、サーバー 10.4) SSL 接続 (プロトコル: TLSv1.2、暗号化方式: ECDHE-RSA-AES256-GCM-SHA384、ビット長: 256、圧縮: オフ) "help" でヘルプを表示します。 testdb=>
$PGPASSWORD
にパスワードを格納する か、 .pgpass
ファイルに諸々記載する があると思いますが、後者はうまくいかなそうです。
.pgpass
ファイルのセパレータが :
ですが、aws rds generate-db-auth-token
が生成する token に :
が利用されているからです。< HTTP/1.1 200 OK
< HTTP/1.1 403 Forbidden
.pgpass
に登録してしまってセミコロンが暴発した 時< HTTP/1.1 503 Service Unavailable
以上、速報レベルですが、うまくできましたというログです。
備忘録的な何かです。
自宅サーバ(もどき) に、Ubuntu Server 18.04 LTS をインストールしたところ、再起動すると
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... WARNING: Failed to connect to lvmetad.
と出てきて、initramfs shell に飛ばされてしまう、というお話。
Begin: Running /scripts/init-premount ... done Begin: Mounting root file system ... Begin: Running /scripts/local-top ... WARNING: Failed to connect to lvmetad. Falling back to device scanning. done. Begin: Running /scripts/local-premount ... [ 3.599890] Btrfs loaded, crc32c=crc32c-intel Scanning for Btrfs filesystems done. Warning: fsck not present, so skipping root file system [ 3.954848] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: (null) done. Begin: Mounting /usr file system ... Begin: Waiting for /usr file system ... Begin: /scripts/local-block ... done. done. Gave up waiting for /usr file system device. Common problems: - Boot args ( cat /proc/cmdline) - Check rootdelay= (did the system wait long enough?) - Missing modules (cat /proc/modules; ls /dev) ALERT! UUID=XXXXXXXX-YYYY-ZZZZ-AAAA-BBBBBBBBBBBB does not exist. Dropping to a shell! (ここでの UUID=XXXXXXXX-YYYY-ZZZZ-AAAA-BBBBBBBBBBBB は、fstab での /usr の UUID
lvm
コマンドで lvm プロンプトに入って、 lvdisplay
を打つと、 /
に割り当てた LV 以外が全部 LV Status NOT available
となっている。
/
に割り当てた LV のみ、 LV Status available
となっている。vgchange -ay
で LV Status available
となった。vgchange -ay
する必要があった。lvmetad
につなげられないことで困っているような雰囲気を感じた。
/usr/share/initramfs-tools/script/local-top
あたりにありそうなことがわかってきた。/usr/share/initramfs-tools/scripts/local-top/lvm2
にそれっぽい関数が出てきた。lvchange_activate() { lvm lvchange -aay -y --sysinit --ignoreskippedcluster "$@" }
lvchange_activate() { # lvm lvchange -aay -y --sysinit --ignoreskippedcluster "$@" vgchange -ay }
/usr
がマウントできない ) し、そもそもそういうために initramfs
があるはずなので、 initramfs
を生成しなおす。$ sudo update-initramfs -u update-initramfs: Generating /boot/initrd.img-4.15.0-34-generic I: The initramfs will attempt to resume from /dev/sda3 I: (UUID=df17b70a-b6bf-11e8-a9e2-60a44c37bf6a) I: Set the RESUME variable to override this.
WARNING: Failed to connect to lvmetad.
の文面自体は見えるので、今後も動向は追っていこうと思います…