/
カテゴリー

ICTSC2018 参加者の皆様、お疲れ様でした。

ICTSC2018 本戦で出題された各問題の解答と解説記事を公開致します。
お待たせしてしまい申し訳ありません。

ミドルウェアグループ LDAPが動かないについては後日公開となります。

問題一覧

ICTSC2018へようこそ

軽量コンテナ

ネットワーク+サーバ連携

近代ネットワーク

ネットワーク機材

仮想化技術

ミドルウェア

ローミドル

それでは、ICTSC2019でお会いできる事を楽しみにしています!

 /
カテゴリー

ICTSC2018 二次予選参加者の皆様、お疲れ様でした。
ICTSC2018 二次予選で出題された各問題の解答と解説記事を公開致します。

問題7 Linuxの解説記事は近日中の公開となります。
 問題7 Linuxの解説記事を公開しました。

※問題8は都合より未出題となりました。

問題一覧

 /
カテゴリー

こんにちは、ICTSC9 問題リーダーの金澤です。参加者の皆さん、コンテストお疲れ様でした。

ICTSC9 で出題された各問題の解答と解説記事を公開しました。ここに、各問題の記事へのリンクをまとめます。コンテスト本番から1ヶ月ほどと、大変遅くなってしまって申し訳ありません。

※ 2018/04/02 現在、解説が未公開の問題があります。申し訳ありませんが、今しばらくお待ちください。

ICTSC9 参加者の方は復習に、次回以降参加するつもりの方は予習に役立ててください!

続きを読む

 /

問題文

同期から次の依頼がありました。

「会社の上司から勉強用にとサーバーをいただきました!
Webページを立ててみたかったのでNginxをインストールしようとしていたのですが、

sudo apt-get install nginx
をするとエラーが出てしまってインストールできないんです…
どうしたら良いんですかね…?」

問題を解決して、インストールがエラーや警告なしで成功するようにしてください。

問題のスタート状態

  • サーバーへのHTTP通信が失敗する

問題のゴール状態

  • Nginxがapt-getによってエラーや警告なしにインストールされている
  • サーバーへHTTP通信ができる

トラブルの概要

Nginxをインストールしようとしたがエラーが発生してインストールが完了しない。

解説

今回のトラブルの原因は /var/log 配下にあるファイル全てにi属性(Immutable属性)が付与されていたからでした。

今回のトラブルが起こる流れとして /var/log配下にあるdpkg.logをアップデートしようとするとコピーなどは成功するが、インストール後スクリプト(post_install)の実行時にdpkg.logファイルの権限変更(chmod)が失敗し、インストール失敗(再インストール)としてマークされます
そして、次回インストール時にpost_installスクリプトが実行されるように予約がされます。

なので、Nginx(その他のパッケージ)をインストールしようとすると再インストールがマークされたdpkgが優先的にインストールされようとしますが、同じ理由で再失敗するのでそれ以降のインストールが無視される(インストール失敗とマークされる)といった流れでした。

ですので、今回は以下のコマンドでdpkg.logのi属性をはずしたらインストールは完了します。

また、今回のゴールはNginxがapt-getによってエラーや警告なしにインストールされているも含まれています。
エラーや警告を解決していない回答が多く見られました。
今回エラーや警告が出ていた原因は/var/logのaptディレクトリにもi属性が付与されていたためです。
なので、aptディレクトリもi属性をはずしたら今回のトラブルは解決です。

回答例

50%

$ cd /var/log
$ sudo chattr -i dpkg.log

もしくは

$ sudo rm -rf /var/lib/dpkg/info/dpkg.postinst
$ sudo rm -rf /var/lib/dpkg/info/dpkg.postrm
$ sudo dpkg --configure dpkg

以上のようにNginxのインストールに成功すれば手段は問わず50%の点数を与えました。

100%

$ cd /var/log
$ sudo chattr -i *
$ sudo apt-get install nginx

2行目が sudo chattr -i aptでも問題ありません。

Nginxのインストール時にエラーや警告がでなければ100%の点数を与えました。

採点基準

  • sudo apt-get install nginxで正常にインストールされない。(0%)
  • sudo apt-get install nginxでインストールされHTTP通信はできるが、インストール時にwarningが消えていない。(50%)
  • sudo apt-get install nginx正常にインストールされHTTP通信ができ、インストール時にwarningがでない。(100%)
 /

問題文

通信事業者である「Ictsc Fiber」では最近、MP‐BGPの検証を行っています。 今日も、Loopbackを用いてピアを張り、ルート共有を行う検証を同僚が行っていました。 ですが、上手くピアを張ることができずあなたに助けを求めに来ました。 原因を究明して解決し、正常にピアを張ってください。またピアを張った後に、図に示す「1841-A」の「Loopback 1」のルート共有を行ってください。

トラブルの概要

MP-BGPの設定を行い、Loopback間でピアを張ろうとしたが上手く張れません。以下の図に示す「C1941」と「1841-A」に設定を追記し、ピアを正常に張れるようにしてください。 また、1841-Aの「Loopback 1」のルート情報を共有し、C1941から1841-Aの「Loopback 1」へ疎通可能にしてください。

解説

今回の問題では、MP-BGPと呼ばれる技術を用いてルータ間でのIPv6ルートの共有を行おうとしています。 MP-BGPとは正式名称で「Multi Protocol BGP」と呼ばれ、Ipv4以外のプロトコルに対応しています。そのため、IPv6プロトコルを使用することができます。MP-BGPでも、ピアを確立しルート共有を行うという順番は変わりません。

MP-BGPでEBGPピアを張る際には、BGPと同じ様にEBGP Neighborの設定が必要になります。また、BGPと違ってaddress familyと呼ばれる設定をする必要があります。今回は以下の設定がそれぞれの機器に行われていました。

  • C1941
  router bgp 1
  no bgp default ipv4-unicast
  bgp router-id 1.1.1.1
  neighbor fd00:173::1 remote-as 2
  address-family ipv6 unicast
  neighbor fd00:173::1 activate
  • 1841-A
router bgp 2
  no bgp default ipv4-unicast
  bgp router-id 2.2.2.2
  neighbor fd00:172::1 remote-as 1
  address-family ipv6 unicast
  neighbor fd00:172::1 activate

物理インタフェースを用いるのであれば、これらの設定でピアを張ることができます。


ですが、今回の問題はLoopbackを用いてピアを張る必要があるため、追加で設定を加える必要があります。 実際に追加する必要がある設定は以下になります。

  • C1941
ipv6 route fd00:173::/64 fd00:171::2
neighbor fd00:173::1 update-source loopback 0
neighbor fd00:173::1 ebgp-multihop 2
  • 1841-A
ipv6 route fd00:172::/64 fd00:171::1
neighbor fd00:172::1 update-source loopback 0
neighbor fd00:172::1 ebgp-multihop 2

各機器に設定する項目は同じです。これらの設定を加えることでLoopback間でピアを張ることができます。 追加設定の内容について説明していきます。

ipv6 route ipv6_network_address nexthop

この設定は、IPv6でのスタティックルートを追加するものです。EBGPピアを張る際は、ピアの宛先のアドレスに疎通性がないと張ることが出来ません。初期の設定のままでは、疎通性がないためスタティックルートを追加する必要があります。

neighbor ipv6_network_address update-source loopback 0

ピアを張る際に送るメッセージを送る送信元は、デフォルトでは物理インターフェースに指定されているためLoopback 0 間でピアを張ることができません。そのため、送信元をLoopback 0に指定する必要があります。

neighbor ipv6_network_address ebgp-multihop 2

EBGPピアを張る際の送るメッセージのTTL(Time to Live)はデフォルトで「1」に設定されています。そのため、Loopbackを用いてピアを張る場合、TTLが1より大きくなってしまうためパケットが捨てられてしまいメッセージが宛先に届きません。そのため、この設定によってTTLの数を増やす必要があります。因みに、最後の値の部分を指定しないと、「255」に設定されます。

以上の設定によって、ピアを張ることができます。


さらに、今回の問題では、ピアを張ることが出来たら1841-Aの「Loopback 1」のネットワークをMP-BGPによって共有を行うという指定がありました。それを踏まえてルート共有を行う設定は以下のとおりです。

  • 1841-A
router bgp 2
 address-family ipv6 unicast
 network fd00:174::/64

この設定を行うとMP-BGPでのルート共有が行われます。

回答例

  • C1941
ipv6 route fd00:173::/64 fd00:171::2
router bgp 1
 neighbor fd00:173::1 update-source loopback 0
 neighbor fd00:173::1 ebgp-multihop 2
  • 1841-A
ipv6 route fd00:172::/64 fd00:171::1
router bgp 2
 neighbor fd00:172::1 update-source loopback 0
 neighbor fd00:172::1 ebgp-multihop 2
 address-family ipv6 unicast
 network fd00:174::/64

採点基準

  • 各ルータのLoopback 0に向けてIPv6でのstatic routeが設定されている(30%)
  • neighborを張る送信元をそれぞれの Loopback 0に設定した(60%)
  • ebgp-multihopを2以上に設定している(90%)
  • BGPによって受け取ったルート情報でR1からR2のloopback 1に疎通性が取れる(100%)
 /

問題文

あなたは新入社員のメンターとして研修に参加していました。
ある日、上司に急用が入り、
「今から日曜まで出張に行ってくるから、それまでに研修用のWebサーバにアクセスできることだけ確認しといて!」
と言われました。しかし、指示されたサーバーである http://192.168.9.1 にアクセスしても何も表示されません。

このサーバーはWebサーバーとしてLighttpdがインストールされており、現在の状態に戻す方法がわかっていれば自由に設定を変更することは許されています。

Webサーバが動作した上で同じ問題が再発しないように修正を行い、以下を上司に報告してください。
– トラブルの原因
– 解決のために行ったコマンド
– 行った変更を元に戻すためのコマンド

情報

  • IPアドレス: 192.168.9.1
  • ユーザー: admin
  • パスワード: hello-world
  • インストールされているWebサーバー: lighttpd

問題のスタート状態

  • サーバーへのHTTP通信が失敗する

問題のゴール状態

  • サーバーへHTTP通信が成功し、ブラウザから見るとLighttpdのプレースホルダのページが表示される
  • 来年以降同じ問題が再発しないよう設定する

トラブルの概要

systemdで起動時のターゲットにWebサーバ(lighttpd)が登録されていない

解説

この問題は、Ubuntu 18.04のinitシステム(起動時に最初に呼び出される、その他に起動に必要なアプリケーションを起動したりシステムを管理するためのアプリケーション)であるsystemdを用いた環境で「サービス」(デーモン)が起動していないというトラブルです。
使用しているサーバーはUbuntu 18.04を使用しています。このディストリビューションでは、initシステムとしてsystemdを採用しています。
initrcやinitngなどを使用しているシステムでは /etc/init.d/ 配下にあるファイルを用いて起動していますが、systemdを使用したシステムでは systemctl というコマンドを使用します。

また、OS起動時に自動起動する設定も同じコマンドで行います。

今回のトラブルでは、Webサーバーはインストール済みの状態ですので、このコマンドを使用してサービスを起動/停止することで解決可能です。

systemctl start lighttpd
systemctl stop lighttpd

また、この変更のみでは自動起動はしないため、設定を元に戻すコマンドは必要ありません。
しかし、自動起動設定を行った場合は自動起動設定を停止するコマンドも投入する必要があります。

自動起動設定コマンドと停止コマンドは以下のとおりです。

systemctl enable lighttpd
systemctl disable lighttpd

回答例

お疲れ様です。解答を送信します。

今回のトラブルは、lighttpdが起動していないことが原因でした。
lighttpdはインストール済みのため、以下の手順でWebサーバの起動をすることができます。

Webサーバの起動

systemctl start lighttpd

また、同じ問題が再発しないよう、研修終了までWebサーバを自動起動するようにします。

Webサーバの自動起動の設定

`systemctl disable lighttpd

これらの設定を元に戻す方法は以下のとおりです。

Webサーバの停止・自動起動の解除

systemctl stop lighttpd
systemctl disable lighttpd

採点基準

  • 上記手順をすべて達成して100%
  • 自動起動をしていない -10点
  • 元に戻す方法を記述していない -10点

講評

この問題は「コンテストサイトの使い方を学ぶための簡単な問題」という位置づけだったこともあり、とても簡単な問題でした。そのおかげで、全チームに満点を付与することができました。作門者もにっこり喜んでいます。
Webサーバの設定ファイルを変更したチームもありましたが、もしかしたら惰性や習慣で systemctl start lighttpd をしてしまったのかなと個人的には思っています。
私も以前に似たようなことを行い、問題解答不能になったことがありました。
実際にサーバーに対して操作を行う際には、原因の調査と解決を分けて考えることで
「なぜこのトラブルが起きているのか?」を正しく判断することができ、
また「どのようにしてこのトラブルを解決するか」が分かれば、トラブル解決の途中で新たなトラブルに遭遇した際にも
「どのようにして環境をロールバックするか」を理解することにつながると思います。
トラブルが起きている当初の環境への復旧(ロールバック)は「ICTSCの問題環境」では簡単に行えますが、実務環境では大抵できません。ここからの締めの文章が浮かびませんが、みなさん頑張ってください。

問題タイトルは、「新人(入社数ヶ月)が新人(入社数日)のメンターになり、新人研修を行っている」ようなシチュエーションを考えて付けましたが、問題文を作る能が無く、なーんか変な内容になってしまいました。

 /

問題文

通話が繋がらない!

離れたオフィス間でも円滑にミーティングをできるように社内ミーティングサービスを運用している。
セキュリティ強化として入社した新入がLinux Routerにとある変更を行ったところ、社内ミーティングサービスが動作しなくなった。

このままだと、別支店のチームがミーティング参加ができなくなる!

一刻も早く修正せよ!

情報

  • 社内ミーティングサービスURL: https://192.168.8.19/

Linux router X

IPアドレス: 192.168.8.1
ユーザー: admin
パスワード: a3nVn22U

Linux router Y

IPアドレス: 192.168.8.9
ユーザー: admin
パスワード: PGrydZ1

Application Server

IPアドレス: 192.168.8.19
ユーザー: admin
パスワード: ani8EZu

使用手元機材の情報

Client A(支店A)

2960-A: FastEthernet 0/1

Client B(支店B)

2960-A: FastEthernet 0/2

問題のスタート状態

参加者PC同士での社内ミーティングサービスを使用したビデオ通話ができない。

問題のゴール状態

参加者PC同士での社内ミーティングサービスを使用したビデオ通話ができる。

構成

注意事項

この問題で使用するブラウザは「Google Chrome」と「Firefox」のみです。
これら以外のブラウザでは問題回答ができませんので、このブラウザで動作確認をしてください。

この問題を解く際は、参加者PCを無線Wifiに接続せず使用手元機材の情報に記述されている有線LANポートのみに接続してください。
参加者は自身のPCからApplication ServerにHTTPSでアクセスすることで社内ミーティングサービスを利用することができます。
このサービスではHTTPS通信に自己署名証明書を使用をしております。そのため、ブラウザからアクセスした際に証明書の警告がされます。

トラブルの概要

社内ミーティングサービスではWebRTCが使用されており、ビデオ通話などのメディアデータの送受信は基本的にP2PでClient同士が通信するものである。
今回Client同士がP2P通信するための経路情報が互いのLinux routerに登録されていないために発生したトラブル。

解説

トラブルの概要の通り、Linux router XとLinux router Yにて、互いの経路情報を登録する。

永続化については問題文に明記していないので、永続化の有無については得点への反映はない。

解答例

Linux router X

# # 経路追加
# route add -net 192.168.8.8 netmask 255.255.255.248 gw 192.168.8.18
# # 永続化
# cat /etc/network/if-up.d/branch-b-routing
#!/bin/sh
/sbin/route add -net 192.168.8.8 netmask 255.255.255.248 gw 192.168.8.18

Linux router Y

# # 経路追加
# route add -net 192.168.8.0 netmask 255.255.255.248 gw 192.168.8.17
# # 永続化
# cat /etc/network/if-up.d/branch-a-routing
#!/bin/sh
/sbin/route add -net 192.168.8.0 netmask 255.255.255.248 gw 192.168.8.17

講評

ICTSC 2018お疲れ様でした。

今回の問題は、解答を見てしまえばとても簡単な解決方法だったかと思います。
ソースコードのほとんどは、ICTSC2018 一次予選のWebRTC問題とほとんど一緒です。

しかし、今回の問題では、テキストチャットがWebRTC通信が確立できていない際に、アプリケーションサーバを介して通信するため、戸惑ったチームも多かったかと思います。

回答率は他の問題に比べ低かったですが、WebRTCに使用されている様々な、プロトコル、技術を考慮している解答も見られ、WebRTCを多くの人に知ってもらいたかった作問者としては非常に嬉しかった結果でした。

 /

問題文

あなたの後輩が「FTPが動かない」と相談してきました。後輩の頼みを断れないあなたはこの問題を見てみることになりました。
どうやら家の外から認証は出来そうなのですが、ディレクトリ一覧を見ることが出来なさそうです。

手元PCから192.168.7.1で接続し、ディレクトリ一覧を取得できるようにしてください。

情報

server

routerがport forwardingを行っているため、routerのIPアドレスにSSHをすればserverに接続することが可能です。

IPアドレス: 192.168.7.1
ユーザー: admin
パスワード: cf1e8c14e54505f6

router

もしログインするのであれば、serverを踏み台にしてアクセスしてください。

IPアドレス: 192.168.7.254
ユーザー: admin
パスワード: f3395cd54cf857dd

トポロジー図

禁止行為

  • 以下の設定を変更してはいけない。
connect_from_port_20=YES
  • 以下のルールを削除・無効化してはいけない。
iptables -A OUTPUT -p tcp --sport 20 -j REJECT

解説

問題文に「家の外から認証は出来そうなのですが、」とあるように、家の外から接続することが出来ないようです。家の外で接続する場合、途中でアドレス変換(NAT)されたり、routerに入力されるパケット(inboundのパケット)を制限されている場合があります。そのため、ACTIVEモードよりもPASVモードで接続する方が接続しやすいでしょう。

まず、192.168.7.1にFTPで接続してみます。

$ ftp 192.168.7.1
Connected to 192.168.7.1.
220 (vsFTPd 3.0.3)
Name (192.168.7.1:root): admin
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pass
Passive mode on.
ftp> ls
227 Entering Passive Mode (192,168,7,129,169,115).
ftp: connect: Connection timed out
ftp>

すると、227 Entering Passive Modeというレスポンスが表示された後タイムアウトになります。このレスポンスの後方にある6つの数字は、PASVモードで接続する際に使用するIPアドレスとポート番号を表しています。RFC959を見てみると次のように説明されています。

DATA PORT (PORT)

The argument is a HOST-PORT specification for the data port
to be used in data connection. There are defaults for both
the user and server data ports, and under normal
circumstances this command and its reply are not needed. If
this command is used, the argument is the concatenation of a
32-bit internet host address and a 16-bit TCP port address.
This address information is broken into 8-bit fields and the
value of each field is transmitted as a decimal number (in
character string representation). The fields are separated
by commas. A port command would be:

PORT h1,h2,h3,h4,p1,p2

where h1 is the high order 8 bits of the internet host
address.

つまり、(192,168,7,129,169,115)という6つ組の数字は、「PASV接続する時は、192.168.7.129:43379に接続してください」という意味になっています。

ですが、192.168.7.129というのは、NAT内でのIPアドレスなので、NATの外から直接接続することはできません。本来であれば、192.168.7.1と表示されてほしいはず。192.168.7.1にアクセスした後に192.168.7.129にパケットが転送されてくれないと困るため、routerに対してrouterが着信した通信を転送する設定(Port forwarding)を入れる必要もありそうです。また、問題文からserverにもiptablesの設定が入っていそうなので、その設定も追記をする必要があるかもしれません。

まず始めに、serverの/etc/vsftpd.confに以下の設定をします。詳しい設定の意味は、こちらを確認すると良いです。ざっくり説明すると「vsftpdはスタンドアロンで動作し、IPv4からの接続を受け付ける。また、PASV接続の際には192.168.7.1の60001~60025番ポートを使用する」という意味になります。この設定を入れたあとは、vsftpdを再起動してください(sudo systemctl restart vsftpd)。

- LISTEN=NO
+ LISTEN=YES
- LISTEN_IPv6=YES
+ LISTEN_IPv6=NO
...
+ pasv_address=192.168.7.1
+ pasv_min_port=60001
+ pasv_max_port=60025

この次に、serverのiptablesの設定を確認してみましょう。

$ sudo iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:domain
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
REJECT tcp -- anywhere anywhere tcp spt:ftp-data /* DON'T REMOVE IT. */ reject-with icmp-port-unreachable

今回、60001番から60025番ポートをFTP用に使おうとしているので、それを許可する設定を入れる必要があります。

$ sudo iptables -A INPUT -p tcp --dport 60001:60025 -j ACCEPT

最後にrouterのPort forwardingの設定を確認してみましょう。

$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere router tcp dpt:ftp to:192.168.7.129
DNAT tcp -- anywhere router tcp dpt:ssh to:192.168.7.129

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.7.128/25 anywhere

先程と同様に、60001番から60025番ポートを転送するような設定を入れる必要があります。

$ sudo iptables -t nat -A PREROUTING --dst 192.168.7.1 -p tcp --dport 60001:60025 -j DNAT --to 192.168.7.129

ここまで設定を入れると、次のようにPASVモードで接続できていることが分かります。

ftp 192.168.7.1
Connected to 192.168.7.1.
220 (vsFTPd 3.0.3)
Name (192.168.7.1:root): admin
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pass
Passive mode on.
ftp> ls
227 Entering Passive Mode (192,168,7,1,234,102).
150 Here comes the directory listing.
226 Directory send OK.
ftp>

想定解法

  • serverの/etc/vsftpd.confに以下の設定を入れた。
- LISTEN=NO
+ LISTEN=YES
- LISTEN_IPv6=YES
+ LISTEN_IPv6=NO
...
+ pasv_address=192.168.7.1
+ pasv_min_port=60001
+ pasv_max_port=60025
  • serverのiptablesに以下の設定を入れた。
sudo iptables -A INPUT -p tcp --dport 60001:60025 -j ACCEPT
  • routerのiptablesに以下の設定を入れた。
sudo iptables -t nat -A PREROUTING --dst 192.168.7.1 -p tcp --dport 60001:60025 -j DNAT --to 192.168.7.129

講評

解答率はだいたい30%くらいでもうちょっと解いてくれる人多いかなと期待してました。作問者自身も中学生とかの頃はよく使っていましたが、最近はsftpで済ませてしまうことがほとんどなので、最近触れる人は意外とFTPを使ったことがないのかもしれないと考えています。

この問題は想定解法以外にもいくつかの解法があります。想定解法ではPASVモードで接続するようにしているのですが、ACTIVEモードで接続するのもこの問題のゴールである「手元PCから192.168.7.1で接続し、ディレクトリ一覧を取得できるようにしてください。」を満たしているため正解としています。中には、ip_conntrack_ftpip_nat_ftpを用いた解法もありましたが、基本的に使っても接続できるようにはならないはずです。想定解法以外の解法についてはいつかどこかで説明できたらなと思っています。

 /

問題文

あなたの部署では IPv6 のネットワークを使用しており、ルータ以下に fd00:10::/64fd00:11::/64 の2つのサブネットがあり、それぞれのサブネットに端末がある。fd00:10::/64 には端末1が存在し fd00:11::/64 には端末2が存在している。

fd00:11::/64 のサブネットでは今まで静的に IPv6 アドレスを割り当てていたが、自動的な割り当てに切り替えることになった。ところが、切り替え作業時にオペレーションミスが発生してしまい、端末2が IPv6 アドレスを失ってしまったらしく、端末1から端末2へアクセスできなくなってしまった。

この状態から切り替え作業を完了させ、端末2に fd00:11::/64 の IPv6 アドレスを自動的に割り当てて端末1からアクセスできるようにしてほしい。なお端末2のアドレスとしては fd00:11::100 - fd00:11::199 の範囲のみが使用を許可されている。

情報

ルータ

IPアドレス: 192.168.10.1
ユーザー: admin
パスワード: w4HcAsJS

端末1

IPアドレス: fd00:10::2
ユーザー: admin
パスワード: w4HcAsJS

ルータからアクセスすることが可能です。

端末2

ユーザー: admin
パスワード: w4HcAsJS

構成

10_ryo_image.png

トラブルの概要

  • 端末2に静的に割り当てていた IPv6 アドレスが消えている
  • DHCPv6 の設定が入っていない

解説・解答例

まず、問題文を読めば以下の事項が要求されているとわかります。

  1. サーバ2に自動的にIPv6アドレスを割り当てる
  2. 自動的に割り当てるIPV6アドレスは fd00:11::100 - fd00:11::199 でなければならない

IPv4であれば、自動的にアドレスを割り当てる場合にはDHCPを利用します。一方でIPv6アドレスを自動的に割り当てる方法としては以下の二つがあります。

  1. Router Advertisement (RA) を利用したステートレス自動割り当て
  2. DHCPv6 を利用したステートフル自動割り当て

ステートレス自動割り当てではサーバがルータからRAというメッセージを受け取り、RAで配布された情報とサーバのインターフェースのMACアドレスを組み合わせてIPv6アドレスを生成します。そのため、特定の範囲内のアドレスを使わせることが不可能です。したがってDHCPv6を使わなければならないことがわかります。

そこでルータの fd00:11::/64 のインターフェースにDHCPv6の設定を行いましょう。

まずはルータにsshします。

$ ssh admin@192.168.10.1
Welcome to VyOS

sshの際にルータがVyOS であることがわかります。VyOS のコマンドで設定していきましょう。

$ show conf
ethernet eth2 {
address fd00:11::1/64
duplex auto
smp_affinity auto
speed auto
}

コンフィグを見るとeth2fd00:11::/64のインターフェースだとわかります。

$ conf
$ set service dhcpv6-server
$ set service dhcpv6-server shared-network-name eth2 subnet fd00:11::/64 address-range start fd00:11::100 stop fd00:11::199
$ edit interfaces ethernet eth2
$ set ipv6 router-advert send-advert true
$ set ipv6 router-advert managed-flag true
$ set ipv6 router-advert other-config-flag true
$ exit
$ commit; save

address-rangeでIPv6アドレスの範囲を指定します。これは、問題文に指定されている通り fd00:11::100 - fd00:11::199 にしましょう。

またeth2においてRAを有効にします。これは、DHCPv6による割り当てを使う場合でもまずはサーバがルータからRAを受け取る必要があるからです。DHCPv6でIPv6アドレスを配布するにはさらにmanaged-flagを有効にする必要があります。other-config-flagはDHCPv6サーバでネームサーバなどの情報を配布するかどうかのオプションであるため、ここでは有効にしていますが、無効でも良いです。なお VyOS ではother-config-flagに関わらず、デフォルトゲートウェイがRAを配布したインターフェースに設定されるようです。

さて、これでサーバ2にアドレスが割り振られるはずなので見てみましょう。以下のコマンドで割り当てられてい DHCPv6アドレスを確認することができます。

$ show dhcpv6 server leases
There are no DHCPv6 leases.

ところが、予想に反して、割り当てられているIPv6アドレスがありません。ルータとサーバ2の間に何らかのトラブルが発生していることが想定されます。サーバ2にsshしてトラブルシューティングを行いたいところです。しかし「サーバ2が IPv6 アドレスを失ってしまったらしく、サーバ1からサーバ2へアクセスできなくなってしまった」とあるように、サーバ2に割り当てられていた静的なIPv6アドレスは失われてしまっています。

ここで、IPv6のリンクローカルアドレスを使います。IPv6が有効になっている全てのインターフェースには、MACアドレスから自動生成されたリンクローカルアドレスが割り当てられています。これは、その名の通り同じL2にいるインターフェース同士の通信に使用することができます。したがって、ルータからであればサーバ2のリンクローカルアドレスにアクセスすることができます。

サーバ2のリンクローカルアドレスはわからないので探しましょう。そのためには、IPv6のマルチキャストが有効です。IPv6にはリンクローカルなマルチキャストアドレスがあらかじめいくつか定義されており、同じL2に存在する特定の種類のインターフェース全てに通信することができます。ここでは、リンクローカルな全てのノードのアドレスを調べるためにeth2からff02::1に ping します。

$ ping6 -I eth2 ff02::1

これを実行すると1つ以上のインターフェースから応答があるはずです。なお、一度通信したことのあるインターフェースのアドレスは以下のコマンドでも調べられます。RAを有効にした後であれば、上記のpingのマルチキャストを行わなくても複数のインターフェースを見つけられるかもしれません。

$ show ipv6 neigh

ここまででサーバ2のインターフェースの候補がわかるはずなので、あとは地道にsshを試していきます。与えられたユーザとパスワードでログインできるのがサーバ2です。なお、リンクローカルアドレスにsshするときはアドレスの末尾に%eth2を追記して、インターフェースを明示する必要があります。

$ ssh admin@{{link local address}}%eth2
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-45-generic x86_64)

ログインに成功するとUbuntu 18.04であることがわかります。iproute2のコマンドでインターフェースを見ると、アドレスが振られていないのがわかります。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:5e:e0:21:7e brd ff:ff:ff:ff:ff:ff
inet6 fe80::5054:5eff:fee0:217e/64 scope link
valid_lft forever preferred_lft forever

Ubuntu 18.04ではネットワークインターフェースの管理にNetplanというソフトウェアを使っています。設定ファイルは/etc/netplan/以下にあります。今回は/etc/netplan/99-network-config.yamlが存在し、以下のように書かれています。

network:
version: 2
ethernets:
eth0:
dhcp4: false
accept-ra: false
gateway6: fd00:11::1

ここからRAが無効になっているとわかります。これではDHCPv6によるアドレス割り当てを行うことができません。そこで、RAとDHCPv6を有効にします。また、ゲートウェイはRAによって設定されるので、静的な設定は消してしまいます。

network:
version: 2
ethernets:
eth0:
dhcp4: false
dhcp6: true
accept-ra: true

書き換えて保存したら、以下のコマンドで設定を反映させます。

$ sudo netplan apply

すると今度はDHCPv6によって割り当てられたアドレスが確認できるはずです。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:5e:e0:21:7e brd ff:ff:ff:ff:ff:ff
inet6 fd00:11::199/128 scope global dynamic noprefixroute
valid_lft 43196sec preferred_lft 26996sec
inet6 fe80::5054:5eff:fee0:217e/64 scope link
valid_lft forever preferred_lft forever

問題が解決したかどうか確かめるために、サーバ1からこのアドレスにpingしてみましょう。

$ ssh admin@fd00:10::2
$ ping fd00:11::199
PING fd00:11::199(fd00:11::199) 56 data bytes
64 bytes from fd00:11::199: icmp_seq=1 ttl=63 time=1.38 ms
64 bytes from fd00:11::199: icmp_seq=2 ttl=63 time=1.17 ms

成功していれば、問題解決です。当初の目的通りに、サーバ2に特定の範囲のIPv6アドレスを自動的に割り当てることができました。

採点基準

想定解法の場合

  • サーバでRAを設定している: 60点
  • サーバでDHCPv6を設定している: 70点
  • 端末2にリンクローカルアドレスで接続している: 70点
  • クライアントを正しく設定している: 40点

その他の解法の場合

  • IPv6アドレスが正しく割り当てられている: 140点
  • 端末1から端末2へpingが通る: 100点

参考

この問題を解く、あるいは解説を理解するにあたって参考となるウェブページを上げておきます。

  • RAとDHCPv6について: https://www.infraexpert.com/study/ipv6z5.html
  • IPv6ユニキャストアドレスについて: https://www.infraexpert.com/study/ipv6z3.html
  • IPv6マルチキャストアドレスについて: https://www.infraexpert.com/study/ipv6z10.html
 /

問題文

MSPに管理を依頼している踏み台サーバから中にあるアプリケーションサーバに、公開鍵認証でログインできなくなってしまった。君たちの手元からアプリケーションサーバには疎通がなく、踏み台サーバーを経由してsshを行う必要がある。困ったことに、アプリケーションサーバのsshd_configにはパスワード認証を許可する設定がされていない。

どうやらログインできなくなる前が新入社員が踏み台サーバーでなんらかの作業を行っていたらしい、なんとかしてアプリケーションサーバにログインできるようにしてほしい。

社内ではログイン方法がマニュアル化されているため、かならず下記コマンドでログインができるようにしてほしい

ちなみに、管理を依頼している会社は怠け者集団で月曜日までは対応ができないとのことだ。

情報

踏み台サーバ (wow_bastion)

IPアドレス: 192.168.6.1 (踏み台), 192.168.6.129 (アプリケーションネットワーク) ユーザー: admin  パスワード: n0stack/n0stack

アプリケーションサーバ (wow_target)

IPアドレス: 192.168.6.130 ユーザー: admin  パスワード: なし (公開鍵認証)

目標サーバのadminユーザーには、 踏み台サーバの /home/admin/.ssh/id_ecdsa に対応する公開鍵が設置されている。

トラブルの概要

公開鍵認証を用いたsshを行うとき、ローカルの同名ファイル(id_ecdsaとid_ecdsa.pubなど)がキーペアになってない場合に、認証がスキップされてログインできない問題。

解説

この問題は、踏み台サーバから公開鍵認証を用いたsshログインができなくなるトラブルです。

LinuxのSSHクライアントから公開鍵認証で接続する際は、 -i で公開鍵を選択するか、 ~/.ssh の配下にあるファイルが読み込まれます。 ファイルが読み込まれた際に、秘密鍵の名前に加えて .pub がついたファイルが存在していた場合、そのファイルが秘密鍵とペアである公開鍵かのチェックが行われ、一致しなかった場合はログインが出来ないという問題があります。 また、この問題は .pub ファイルが存在しない場合には行われず、接続に成功します。

踏み台サーバの作業履歴をみるとホームディレクトリのtarballが展開されて、公開鍵が上書きされていることがわかります。

想定回答としては、ssh-keygen コマンドを用いて秘密鍵から公開鍵を再生成する事を想定しています。 ssh-keygen -y -f ~/.ssh/id_ecdsa > ~/.ssh/id_ecdsa.pub

それ以外にも、 .pub ファイルが存在しない場合に接続が成功することがあるため、当該ファイルを削除しても解決可能ですが、この問題の場合は一部減点をしています。 rm ~/.ssh/id_ecdsa.pub

回答例

お疲れ様です。解答を提出いたします。

ssh admin@192.168.6.130 -vvv で踏み台のid_ecdsaのオファーが途中でスキップされていることを確認しました。

history で ~/pubkey.tar.gz が展開された形跡があることを確認しました。

ssh-keygen -l -f ~/.ssh/id_ecdsa ssh-keygen -l -f ~/.ssh/id_ecdsa.pub でこの2つのファイルがキーペアになっていないことを確認しました。

mv ~/.ssh/id_ecdsa.pub ~/.ssh/id_ecdsa.pub.old のようなコマンドで展開された公開鍵のバックアップを取りました。

ssh-keygen -yf ~/.ssh/id_ecdsa > ~/.ssh/id_ecdsa.pub でキーペアになる公開鍵を生成しました。

ssh admin@192.168.6.130 でログインできることを確認しました。

採点基準

/home/admin/.ssh 内に配置されている id_ecdsa と id_ecdsa.pub がキーペアでなくなっていることに気づく: 50%

目標サーバに /home/admin/.ssh/id_ecdsa を用いでログインができる 100%

/home/admin/.ssh/id_ecdsa から公開鍵を生成していない場合は減点

 /

問題文

あなたが所属している会社では、社内専用のWebサイトを別のサーバにリプレイスしました。Webサイトの移行はトラブルなく完了しましたが、後輩が担当していたネットワーク部分が上手く動作せず、社内ネットワークからWebサイトへアクセスできません。自分では手に追えなくなった後輩があなたに泣きついてきました。

「Webサイトには 『 http://192.168.15.125 』 でアクセスするんですが、社内ネットワークからアクセスすることが出来なくて……。多分、ルータのNAT周りの設定がおかしいと思うんですがどこを直したらいいんでしょうか……? 先輩助けてください!」

トラブルの原因を突き止めて、サイトが正常に閲覧できるようにしてください。

情報

  • 使用する手元機材 : AR2050V
  • ユーザー : admin
  • パスワード : IWgrk2Dz
  • 社内ネットワーク
  • IPアドレス:DHCPで配布
  • AR2050VのLANポートに接続すると社内ネットワークに入れる
  • Webサーバ
  • 社内ネットワークからWebサーバへアクセスするためのIPアドレス:192.168.15.125
  • なおWebサーバの本来のホストは192.168.15.125ではなく、192.168.15.32である。
  • Webサーバを操作することはできない

問題に関する禁止事項

  • NATルールを変更しない
  • 物理配線を変更しない
  • IPアドレスを変更しない
  • DHCPを変更しない

報告書を書く際の必須事項

  • 追記・修正するためのコンフィグ
  • 『 http://192.168.15.125 』にアクセスした結果

トラブルの概要

双方向NATをするための以下の要素が正しく設定されていないため、参加者PCからWebサーバへアクセスできません。

  • proxy arp の設定が漏れている
  • zone localの内容が間違っている
  • zone globalの内容が間違っている

解説

Webサーバへアクセスできないのは、双方向NATするための条件が揃っていないことが原因です。

双方向NATとは、1台のNATデバイスで「内部の送信元アドレス変換」と「外部の送信元アドレス変換」を同時に行うNATのことです。双方向にアドレスが変換されることから、内部ホストと外部ホストの双方ともお互いのIPアドレスを知ることなく通信することが可能になります。

双方向NATの条件がそろっていないことが原因ということですが、NATの設定から順を追ってみていこうと思います。

NATの確認

まずはNATの設定を確認しましょう。

今回のNAT設定は以下のようになっていました。

nat
rule 10 masq any from private to global with src global.wan.client
rule 20 portfwd any from private to local.lan.server with dst public.wan.server

今回は、スタティックNATで双方向NATを実現しています。

1行ずつ見ていきましょう。

「内⇒外」方向のスタティックNAT

rule 10 masq any from private to global with src global.wan.client

上記の設定は、

  • rule コマンドで masq アクションを指定されているため、「内⇒外」方向へのスタティックNATである。
  • すべてのアプリケーションの送信元エンティティー「from private」で宛先エンティティー「to global」のとき、送信元IPアドレスを「with src global.wan.client」に変換する。

を表します。

次に、このNATに関するエンティティーの内容を確認します。

zone private
network lan
ip subnet 192.168.15.64/26
host client
ip address 192.168.15.70
ip address 192.168.15.71
ip address 192.168.15.72
ip address 192.168.15.73
ip address 192.168.15.74
ip address 192.168.15.75
ip address 192.168.15.76
ip address 192.168.15.77
ip address 192.168.15.78
ip address 192.168.15.79
ip address 192.168.15.80
!
zone global
network wan
ip subnet 192.168.15.0/24
host client
ip address 192.168.15.125

送信元エンティティーである「private」は、ルータのLANポートに接続したときに降ってくるDHCPが指定されています。

宛先エンティティーである「global」は、NATの設定通りであるとすると、送信元IPアドレスを変換するための条件(ネットワーク定義にWebサーバが属するネットワークアドレス、ホスト定義に特定のipアドレス)が設定されているはずですが、でたらめな条件になっていることが分かります。

よって、このゾーン定義の内容を修正する必要があります。

no zone global
zone global
network wan
ip subnet 192.168.15.0/26
host client
ip address 192.168.15.33

送信元ipアドレスを変換するための「with src global.wan.client」は、show runnning-configを確認すると ip route 192.168.15.33/32 eth1 が設定されているので、192.168.15.33 を指定すると良さそうです。

「外⇒内」方向のスタティックNAT

rule 20 portfwd any from private to local.lan.server with dst public.wan.server

上記の設定は、

  • ruleコマンドで portfwd アクションを指定されているため、「外⇒内」方向へのスタティックNATである。
  • すべてのアプリケーションの送信元エンティティー「from private」で宛先エンティティー「to local.lan.server」のとき、宛先IPアドレスを「with dst public.wan.server」に変換する。

を表します。

次に、このNATに関するエンティティーの内容を確認します。

zone local
network lan
ip subnet 192.168.15.0/24
host server
ip address 192.168.15.33
!
zone private
network lan
ip subnet 192.168.15.64/26
host client
ip address 192.168.15.70
ip address 192.168.15.71
ip address 192.168.15.72
ip address 192.168.15.73
ip address 192.168.15.74
ip address 192.168.15.75
ip address 192.168.15.76
ip address 192.168.15.77
ip address 192.168.15.78
ip address 192.168.15.79
ip address 192.168.15.80
!
zone public
network wan
ip subnet 192.168.15.0/26
host server
ip address 192.168.15.32
!

送信元エンティティーである「private」は、1行目のNATのときと同じなので割愛します。

宛先エンティティーである「local.lan.server」は、問題文に書かれていた、社内ネットワークからWebサーバにアクセスするときのIPアドレス192.168.15.125 が当てはまるはずですが、1行目のNATと同様に、ネットワーク定義もホスト定義もでたらめになっています。

よってこのゾーン定義を修正する必要があります。

no zone local
zone local
network lan
ip subnet 192.168.15.64/26
host server
ip address 192.168.15.125

宛先ipアドレスを変換するための「with dst public.wan.server」は、Webサーバの本来のipアドレスが指定されているので、修正する必要はありません。

代理応答機能を追加する

Firewallはすべてのエンティティー間を許可しているので問題ないため、NAT周りはすべて修正出来ました。

双方向NATでは、ルータ本体に設定されていないIPアドレスを使用しています。

よって、そのIPアドレスに対してルータが代理応答する必要があります。

特定のIPアドレス範囲を代理応答させるためには local-proxy-arp コマンドを用いて設定する必要があります。

しかし、show runnning-configを確認した限り、設定されていないようなので、追加設定をしなければなりません。

local-proxy-arp 192.168.15.125/32
local-proxy-arp 192.168.15.33/32

上記の設定を有効にするためには、該当するインターフェースに対してリミテッドローカルプロキシーARPを有効にする必要がありますが、インターフェースvlan43とインターフェースeth1どちらとも有効になっているので、設定する必要はありません。

回答例

!
local-proxy-arp 192.168.15.125/32
local-proxy-arp 192.168.15.33/32
!
no zone global
zone global
network wan
ip subnet 192.168.15.0/26
host client
ip address 192.168.15.33
!
no zone local
zone local
network lan
ip subnet 192.168.15.64/26
host server
ip address 192.168.15.125
!

採点基準

  • proxy arp の設定が正しく追加されている(30%)(計30%)
  • zone global の設定が正しく修正されている(15%)(計45%)
  • zone local の設定が正しく修正されている(15%)(計60%)
  • client から 192.168.15.125 にブラウザからアクセスするとWebページが閲覧できる(40%)(計100%)

 

 /

問題文

ここに以前新入社員が作ったXenサーバーと、業務での検証用のVMがあります。

今年の新入社員に、Xenサーバーに入っているVMの更新を依頼し、作業を行ってもらっていましたが、

アップデートを行い再起動をしたらVMがインターネットに接続できなくなったと連絡を受けました。

このサーバーは今日は使用しませんが、新入社員の明後日以降の実習環境になるため、それまでに復旧させなければならず、

また、あなたは明日予定があり早く退社しなければならず、

明日の業務終了時間である日曜日の15:00(コンテスト終了時間)までに復旧させる必要があります。

また、新入社員の研修を兼ねているため、メンターであるあなたは今年の新入社員に「なぜダメだったのか」を説明する必要があり、

新入社員の教育につなげる必要があります。

このVMがインターネットに接続できない原因を突き止め、起動させてください。

また、その原因を説明してください。

情報

Xenの動いているサーバー

IPアドレス: 192.168.5.1

ユーザー: admin

パスワード: xenhost

OS: Ubuntu 18.04 ( Xen Hypervisor Kernel )

Xen上のゲストVM

IPアドレス: 192.168.5.100

ユーザー: root

パスワード: なし

OS: ArchLinux ( Para-Virtualization )

SSHサーバーは動作していません。ping疎通ができればOKです。

構成

UbuntuがDom-0として稼働し、ArchLinuxがDom-Uとして稼働していた

解説

この問題はXenサーバのカーネルに原因があり発生していました。
仮想マシンが使用しているカーネルのバージョンと、Xenサーバ側が仮想マシンの起動に指定しているカーネルのバージョンが一致していません。その状態でも仮想マシンの起動はできるのですが、Xenサーバが指定したカーネルのネットワークモジュールが見つからないためNICを認識せず、外部と通信できません。

解決方法は以下の3つがあります。未完

  1. arch.cfgに `bootloader = “pygrub”` を追加しkernel, ramdiskとextraを消してarchを起動
  2. ゲストマシン上で動作しているvmlinuz-linuxとinitramfs-linux.imgをXenサーバにコピーし、それを使って起動させる
  3. Xenサーバのキャッシュから圧縮されたカーネルを解凍しそれを使って起動させる

それぞれについて解説をしていきます。

まず1つ目は 起動する際に使用するDomain-Uの設定ファイルである arch.cfg に以下の操作をします。
bootloader = "pygrub" を追加
– kernel, ramdiskとextraの行を削除
その後、編集後のファイルを使って sudo xl create arch.cfg を実行し仮想マシンを起動します。そうすると起動時に仮想マシンのディスクに設置してあるブートローダーであるgrubの設定ファイルを読み、ゲストの起動時に「ゲストのディスクに実際にインストールされたカーネル」で起動することができます。
その結果、正しいカーネルモジュールを使用することができるようになり、NICが認識され外部と通信できるようになります。

編集前

name = "arch"
kernel = "/guest/vmlinuz-linux"
ramdisk = "/guest/initramfs-linux.img"
extra = "root=UUID=24225d68-7d38-41fa-b8b5-d8b6c7cfa3b9 rw"
memory = 768
hostname = "arch"
disk =  [ "phy:/guest/arch.img,xvda,w" ]
vif = [ 'mac=00:16:3e:00:00:01,bridge=xenbr0,vifname=arch' ]

編集後

name = "arch"
bootloader = "pygrub"
memory = 768
hostname = "arch"
disk =  [ "phy:/guest/arch.img,xvda,w" ]
vif = [ 'mac=00:16:3e:00:00:01,bridge=xenbr0,vifname=arch' ]

2つめは、動作している仮想マシンのディスクをXenサーバ側にマウントし、仮想マシンのカーネルをXenサーバにコピーします。仮想マシンのカーネルを使用して起動することでNICが認識され外部と通信が可能になります。以下のコマンドを順に実行すると、起動した仮想マシンがNICを認識し外部と通信が可能となります。

<br />[Xenサーバ]$ sudo mount -t ext4 -o loop,offset=1048576 /guest/arch.img /mnt

[Xenサーバ]$ sudo cp /mnt/boot/vmlinuz-linux /guest/

[Xenサーバ]$ sudo cp /mnt/boot/initramfs-linux.img /guest/

[Xenサーバ]$ sudo xl create -c arch.cfg

3つめは仮想マシン内にXenサーバが指定しているバージョンのカーネルが残っていました。それを使って起動すると同様にNICが認識され外部と通信が可能になります。以下にカーネルのバージョンを合わせて起動するコマンドを記載します。

<br />[仮想マシン]# pacman -U /var/cache/pacman/pkg/linux-4.19.1.arch1-1-x86_64.pkg.tar.xz

[仮想マシン]# reboot

講評

この問題の解答を提出した8チームのうち完全解答したチームは4チームでした。私の想定では3つの想定解のうち1個目の pygrub で解いて、他の解答はしてこないだろうと思っていたら完全解答した4チーム全てが pygrub を使わずに来たので驚きました。さらに1チームだけ仮想マシン内のキャッシュから起動させていたのでよく気づいたなと思いました。

解答数が少なかったので難しすぎたかなと思いましたが、完全解答したチームはすごいなと思いました。

ちなみに

カーネルのバージョンはfileコマンドで確認することもできます。

 /

問題文

さて、突然ですが超有名大企業ICTSC Comに入社した新入社員のあなたのミッションは、SRv6を使ってHostAからHostBへの通信の際にIDS(Snort)をサービスチェインして通るようにするということを任されました。
しかし現在はSRv6でHostAからHostBへ通信はIDS Nodeを通らずに通信をしてしまっています。
これをIDS Nodeを通ってからHostBに通るようしてほしい。

HostA: 10.0.0.1/24から HostB: 10.0.1.1/24にPingが飛ばせています。
この状態ではIDS Nodeを通らずHostAからHostBへSRv6を使ってルーティングされています。

IDS Nodeではnetwork namespaceで切り分けられたLinuxとSnortが内部に存在します。残念ながらSnortはディフォルトではSRに対応できていないため注意してください。またSnort自身の設定は変えなくても問題ないように設定されています。
そしてちゃんとパケットが流れればSnortのコンソールを確認するとアラートが流れることが確かめることができます。

以下にトポロジーと認証情報を添付するので確認してみてください。

情報

全てのホストは以下情報で入れます
ユーザー: admin
パスワード: hello_5g

以下のIPアドレスはManagementのための接続アドレスです。

Host A

IPアドレス: 192.168.12.6

Router 1

IPアドレス: 192.168.12.1

Router 2

IPアドレス: 192.168.12.2

Router 3

IPアドレス: 192.168.12.3

Router 4

IPアドレス: 192.168.12.4

IDS

IPアドレス: 192.168.12.5

Host B

IPアドレス: 192.168.12.7

構成

問題スタート

HostAからHostBにPingが飛ばせる。この状態ではAからBへSRv6を使ってルーティングされてる

問題ゴール

HostAからIDSを通ってHostBにPingが飛ばせる様になる。
IDSではICMPを認識して検出ができる.

注意事項

  • 必ずSRv6の機能をつかうようにしてください。
  • トラブルはSRだけとは限りません。あらゆる事がありえます。
  • SnortはIDSが立ち上がっている中でnetwork namespace(veth)で区切られている。以下の方法で簡単に確認ができます。

下には便利なチートシートです。

# srextを使うときはこれを実行してからではないと動きません(公式ドキュメントから抜粋)
sudo depmod -a
sudo modprobe srext

# vethにpacketが通ってきているか見たいとき
ip netns exec Snort tcpdump -i veth0-Snort

# Snort側のnamespaceに移る
ip netns exec Snort bash

# Snortでのアラートが見たいとき(exec Snort bashをした後に使える)
Snort -c /etc/Snort/Snort.conf -A console

トラブルの概要

SFCをしたいができていない。

解説

この問題は、2つのIPv4対応ホスト(hostA and hostB)がSegment routing over IPv6 dataplane(SRv6)を介して通信できるようにして、サービスチェインを実装する問題でした。

トポロジーの細かい要素としては以下のようになります。

  • Router
    • R1,R3,R4: SRv6をサポートするルーター
    • R2: v6だけサポートするルーター
  • IDS: namespaceで区切られたSnortが動作しているサーバ

実際にパケットの動きを見ていきましょう。

まず今回の基本設定の状態はAからBへのトラヒックはR1,R2,R3,R4を通じてBへ渡されます。
実際のフローを少し細かく文章化すると以下のようになります。

IPv4のペイロードがHostAからHostBへ送信される

IPv4のペイロードがHostAから送信されます。
ここではSegment routing header(以下SRH)は付与されず、宛先がHostBになっているIPv4パケットとして送信されます。

パケット構成は以下のようになります。

  • Ethernetヘッダ
  • IPv4
    • 送信元アドレス: HostA
    • 送信先アドレス: HostB

HostAから送信されたパケットがR1に到着

R1では以下の作業が行われます。
– IPv6カプセル化をする
– 2つのノードを対象にするヘッダであるSegment Routing Header(SRH)を挿入しカプセル化をするい

SRHの中にはロケーター情報として、R3,R4を経由するという順序情報と、Segments Left(SL)というSRに対応したルーターを残りいくつ通るかの情報が記載されています。

この作業が終わった後のパケット構成は次のようになります。

  • Ethernetヘッダ
  • IPv6ヘッダ
    • 送信元アドレス: R1::1
    • 宛先アドレス: R3::bb
  • SRH
    • ロケーター情報: R4::bb, R3::bb
    • Segments Left(SL): 1
  • IPv4
    • 送信元アドレス: HostA
    • 送信先アドレス: HostB

上記情報から、IPv6ヘッダの指し示す宛先がR3であるため、R1のルーティングテーブルを見てパケットはR2へと転送されます。

R1から転送されたパケットがR2に到着

R2ではSRv6に対応するための設定は投入していません。
しかし、IPv6の経路情報はR2にインストールされているため、IPv6ルーティングによりR3に転送することができます。

R2から転送されたパケットがR3に到着

R3ではSRv6に対応するための設定が投入されているため、R3::bbに対応する操作を実行し、次の処理を行えるようにするためにEnd動作をします。
End動作により、IPv6ヘッダの値とSRHのSegments leftの値が書き換わります。

  • Ethernetヘッダ
  • IPv6ヘッダ
    • 送信元アドレス: R1::1
    • 宛先アドレス: R4::bb
  • SRH
    • ロケーター情報: R4::bb, R3::bb
    • Segments Left(SL): 0

この情報から、次はR4へとパケットを転送します。

R3から転送されたパケットがR4に到着

R4がSRv6網の終端となります。
この先のネットワークはIPv4ネットワークで、SRv6とIPv6のカプセル化を解除する必要があるため、End.DX4動作をしてカプセル化の解除を行います。

その際、具体的には外部のIPv6ヘッターを除去し、R3でSRv6の設定(function)により決められたIPv4 Next hopへとパケットを転送します。

  • Ethernetヘッダ
  • IPv4
    • 送信元アドレス: HostA
    • 送信先アドレス: HostB

上記の手順により、HostBにPing Requestを送信することができました!

次はPing Replyパケットが送信されるまでのフローを見ていきましょう。

問題出題状態では、R3を通らずに R4 -> R3 -> R1 のようにパケットが転送されるようになっています。

IPv4のペイロードがHostBからHostAへ送信される

IPv4のペイロードがHostBから送信されます。

  • Ethernetヘッダ
  • IPv4
    • 送信元アドレス: HostB
    • 送信先アドレス: HostA

HostBから送信されたパケットがR4に到着

R4では以下の作業が行われます。
– IPv6カプセル化をする
– 2つのノードを対象にするヘッダであるSegment Routing Header(SRH)を挿入しカプセル化をする

その後のパケットは以下のようになります

  • Ethernetヘッダ
  • IPv6ヘッダ
    • 送信元アドレス: R4::dd
    • 宛先アドレス: R1::1
  • SRH
    • ロケーター情報: R1::1
    • Segments Left(SL): 0
  • IPv4
    • 送信元アドレス: HostB
    • 送信先アドレス: HostA

上記情報から、IPv6ヘッダの指し示す宛先がR3であるため、R1のルーティングテーブルを見てパケットはR2へと転送されます。

R4から転送されたパケットがR2に到着

R2ではSRv6に対応するための設定は投入していません。
しかし、IPv6の経路情報はR2にインストールされているため、IPv6ルーティングによりR1に転送することができます。

R2から転送されたパケットがR1に到着

R1がSRv6網の終端となります。
この先のネットワークはIPv4ネットワークで、SRv6とIPv6のカプセル化を解除する必要があるため、End.DX4動作をしてカプセル化の解除を行います。

その際、具体的には外部のIPv6ヘッターを除去し、R3でSRv6の設定(function)により決められたIPv4 Next hopへとパケットを転送します。

  • Ethernetヘッダ
  • IPv4
    • 送信元アドレス: HostB
    • 送信先アドレス: HostA

ここまでが基本的な状態の設定として問題環境に設定していた状態でした。
SRv6について理解するためのきっかけになったと思います。

では実際の問題を解くフェーズに入っていきます。

今回の問題で行う方策をまとめると、

  • Snortがあるホスト(IDS)を通ってパケットを動かす必要がある
    • しかしSnortはSRv6に対応していない

ということになります。

(ちなみに 普通Snortは別ホストじゃないんですか? という質問については、この問題で使用するVMのリソースがコンテストで使用している物理サーバーのうち一台のサーバーをおおむね専有するほど多く、メモリを節約するためにしょうがなく行った苦肉の策でした。
ですが出題としては全く問題ないのでこのまま出題しました。)

今回のトポロジーから、Snortがあるホストにパケットを転送させるにはR1で付与するSRHのロケーター情報にR5を追加することで、R5を経由することができるようになります。

しかし、SnortはSRv6に対応していません。そのため、一度SRv6のカプセリングを外してIPv4のパケットだけに変換する必要があります。

「SRv6はデータプレーンにロケーション情報等が付与されているだけなので一旦外す」という方法が考えれると思います。
ちょっと意地悪に見えるかなぁと思い、出題的には # srextを使うときはこれを実行してからではないと動きません(公式ドキュメントから抜粋) と書いておいたコードがありました。
このコードについてインターネットで調べると、例えば

いhttps://github.com/netgroup/SRv6-net-prog

というリンクが見つかり、以下のようなそれっぽいfunctionを見つけることができます。

  • End.AD4: Endpoint to IPv4 SR-unaware APP via dynamic proxy
  • End.EAD4: Extended End.AD4 behavior that allow SR-unaware VNFS to be the last SF in SFC

このことから、bbの定義を

srconf localsid add fc00:5::bb end.ad4 ip 192.168.1.2 veth0 veth1

このようにすることで、無事Snortまで通信が転送されます。Snortから戻ってきたパケットは正常にR4に流れていきます。
別解としてEnd.EAD4を利用する方法もありますが、こちらでも問題はありません

具体的な挙動としては、veth0に対して流れてきたパケットのSRHを外して、 IPv4 Payload オンリーにして流してあげるだけです。veth1に戻ってきたら、先程外したSRHを再度付与します。
これで無事通信をIDSを通じてhostBへ行くことができました!

問題作成の狙いとお気持ち

この問題は次世代ネットワークについての知識をつけてほしいということから作りました。そもそもほぼ全員がSRv6ってなんやねんというところからで辛いかなと思ってたんですが、まずは存在を知ってもらって、その上でおもしろいところや有用性を理解してもらえたら嬉しいなと思って作った問題でした。また、狙いとしてSRv6はほぼmininet以外で遊べる環境というものは公開されていないため直接OSに対して書き込むconfigとかがあまり見ることができないというのがあります。なので今回は公開をすることでトラコン参加者以外も幸せになるおもしろい問題になったんじゃないかと思います。

ちなみにですが実は自動起動の設定にsystemctlを使用したため、問題参加者はそのへんをガサゴソするとconfigがでてきて参考になったかも知れません。
なおホントはもう少し難しい問題にする予定だったんですが、、、これではあまりにも解けなそうではと言われて変更して、変更したやつも、ちょっとむずかしいのでは?と言われてSRのコマンドだけの修正で解ける問に変更されたので Baby とつけていました。ちょっとpwn系のCTF問題みたいなネームみたいですね。
それでも難しいと言われたので誰も挑戦してくれないかなとヒヤヒヤしていましたが、いくつかのチームは挑戦してくれたのでホッとしました笑

回答例

R1のSegment ID table(SID, つまり通るべき経路の指定)をR3,R5,R4の順番でオーダーする
ip route add 10.0.1.0/24 encap seg6 mode encap segs fc00:3::bb,fc00:5::bb,fc00:4::bb dev eth1
IDS NodeのSnortはSRHを処理することができません。よってIPv6 headerを取り外してあげる必要があります。よってサービスチェインのダイナミックプロキシを行う必要があります
srconf localsid add fc00:5::bb end.ad4 ip 192.168.1.2 veth0 veth1
ちなみにR1でR3,R4で指定してR3でR5に行くようにoverSRv6を更にしたらいいのではと思うかもしれないですが、拡張カーネルが必要で今回は対応していないため困難です

これは今回出題したSRv6についての問題を体験できるVagrantFileです。もしよかったらぜひ遊んでみてください!!
https://github.com/takehaya/SRv6_SFC_Example

採点基準

点数となるのはIDSNodeまでの中継するべきノードをSRv6でオーダーされていて50%+その後にダイナミックプロキシされるで満点を与える方針
そもそもオーダーがない場合などは部分点をつけることはしません