ICTSC2024二次予選 Writeup

2024/12/07に公開

ICTSC2024の二次予選に参加しました。メンバーと協力し、なんとかすべての問題について解答を提出できたのでよかったです。
私は5つの問題を解くことができたので、初めてwriteupを書いてみようと思います。今までCTFなどに参加してもwriteupを書けるほど解けたことがなかったので嬉しいです。
間違っているところがあったらご指摘ください。

  • [KOB] VyOS初めてです
  • [MYS] DNSって難しい。
  • [NGX] にゃーん
  • [YFJ] どちらのプロトコルも30年選手
  • [ISI] Welcome to Kubernetes

[KOB] Vyos初めてです

vyos1でのeth1、eth2が逆になっているため、それを修正することで正常に動かすことができます。

delete interfaces ethernet eth1 address '10.10.2.1/24'
delete interfaces ethernet eth2 address '10.10.3.1/24'
set interfaces ethernet eth1 address '10.10.3.1/24'
set interfaces ethernet eth2 address '10.10.2.1/24'

私はtcpdumpでICMPのパケットを見ていたら、OSPFパケットの送信元で気が付きました。

$ tcpdump -n -i eth1 not port 22

手元で触っているときのように物理的な配線が見えないので、なかなか気がつくのに時間がかかりました。

[MYS] DNSって難しい。

unboundの設定を変更することが禁止されているので、パケットフィルターが原因かなあと見当をつけました。試しにOUTPUTを全て許可してみると成功するため、Egressのパケットフィルターが原因とわかります。

iptables -I OUTPUT -j ACCEPT

そこで、Public DNSへのOUTPUTを全て許可した状態で、tcpdumpを用いてPublic DNSへの通信を監視してみると、UDPの通信の中にTCP通信が混ざっていることに気が付きました。

iptables -I OUTPUT -d 8.8.0.0/16 -j ACCEPT
tcpdump -n dst host 8.8.8.8 or dst host 8.8.4.4

DNSサーバーではiptables-persistentを使ってルールを永続化していたため、/etc/iptables/rules.v4にルールを書いて設定を反映させます。

$ sudo vim /etc/iptables/rules.v4
-A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT # この行を挿入する
$ sudo iptables-restore < /etc/iptables/rules.v4

DNSに詳しくないのでわかりませんが、2回目以降の通信でTCPを用いて良いというような記述がRFCにあった気がするので、そこら辺と関係しているのでしょうか。

[NGX] にゃーん

nginxに対して通信すると400が帰ってきますが192.168.255.71:8080に通信すると成功することから、nginxが原因とわかります。

$ client -url http://192.168.255.71
$ client -url http://192.168.255.71:8080

400の場合、エラーメッセージがHTMLで送られてきてるのではと思いました。HTTPなので、tcpdumpを用いてレスポンスの中身を傍受することができます。

tcpdump -n not port 22 -vvv

すると、400 Bad Request: Request Header or Cookie Too Large というメッセージが確認できたので、リクエストヘッダーのバッファーサイズを増やします。

http {
  large_client_header_buffers 4 32k;
}

$ systemctl reload nginx

すると今度は500エラーが帰ってきます。サーバー側のエラーということで、nginxのログを見てみると、レスポンスボディーのバッファーサイズも足りていないようです。

$ tail -f /var/log/nginx/error.log
upstream sent too big header while reading response header from upstream

こちらもバッファーサイズを増やして解決します。

http {
  proxy_buffers 8 32K;
  proxy_buffer_size 32k;
}

$ systemctl reload nginx

[YFJ] どちらのプロトコルも30年選手

トラブル1はチームメンバーが解いてくれて、続きを引き継ぎました。
eBGPなのでルートマップを設定する必要があったようです。もしくは、下記の設定でルートフィルターを無効化することで解決しそうです。

no bgp ebgp-requires-policy

トラブル2は、Server01の時刻がずれていたことが原因でした。
最初は2つのドメインについての設定を見比べたりしていましたが、Server02で実行すると成功することから、unboundかServer01に原因がありそうだなと考えて気がつくことができました。

sudo systemctl enable --now chrony
chronyc sources

[ISI] Welcome to Kubernetes

kubesprayを触るのは初めてでしたが、Kubernetesの問題は私が解くぞと意気込んでいたので解けて安心しました。
3つの問題があり、それらを解決することで正常に動くようになります。

問題1:レジストリサーバの名前解決ができない

下記のような設定を追加して、イントラネットのドメイン hideichi.as.a.service.com に対するDNSリクエストを社内のCoreDNSで解決するようにします。

# inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
nodelocaldns_external_zones:
- zones:
  - hideichi.as.a.service.com
  nameservers:
  - 10.244.10.130
  cache: 5

問題2:PodとServiceに割り当てているIPが社内ネットワークとかぶっている

デフォルトだと、PodとServiceのネットワークは下記のような設定になっていますが、これはレジストリなどがあるネットワーク 10.233.0.0/16 と被っているため変更します。
(問題3にあとから気がついたのでこれが影響していたのかわかりません。CNIの段階でルーティングがこっちに吸われそうなので影響してるかなと思って解答に記載しました。どうだったんだろう...)

# inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
kube_service_addresses: 10.232.0.0/18
kube_pods_subnet: 10.232.64.0/18

問題3:レジストリにHTTPSで接続しようとしている

問題2を修正しても connection refused と出たままだったのでCNI周りが悪いのかなと随分悩みました。PodのEventsを見ていたときにhttpsのURLに接続していたところから気がつくことができました。
コンテナランタイムはcontainerdを使う設定になっていたので、containerdの設定ファイルに下記のような設定を追記します。

# inventory/mycluster/group_vars/all/containerd.yml
containerd_registries_mirrors:
 - prefix: docker-registry.hideichi.as.a.service.com
   mirrors:
    - host: http://docker-registry.hideichi.as.a.service.com
      capabilities: ["pull", "resolve"]
      skip_verify: true

Discussion