/
カテゴリー

概要

情報システム部門に所属しているI君は業務で使用するためにNginxを構築したが、起動せず繋がらない。原因を究明して繋がるようにして欲しい。なおセキュリティご事情的に外部からはファイル等を取得できない環境である。

前提条件

  • aptなどを使用して外部から新規でnginxをインストールすることは禁止されている
  • /etc/netplan/01-netcfg.yamlを変更してはならない
  • /var/lib/apt/lists/以下を変更してはならない

初期状態

/usr/local/nginx/sbin/nginxしてもエラーが出て起動しない。

終了状態

サーバから

curl --http2 localhost

を行いリソースが取得できる。

解説

この問題ではオプション無しでビルドされたNginxにhttp2に関するモジュールが存在していないためエラーが発生しhttp2を使いたいが、起動できないという問題でした。

問題環境内にビルドするためのファイル一式があるので、http2モジュールを含むオプションを行い実行することでnginx.confを変更することなく解くことが出来ました。また、終了条件を満たせていれば良いためnginx.confhttp2を削除することでもcurlが通るためそれも満点としています。

想定解

Nginxを実行すると以下のエラーが確認できる。

sudo /usr/local/nginx/sbin/nginx 
nginx: [emerg] the "http2" parameter requires ngx_http_v2_module in /usr/local/nginx/conf/nginx.conf:36

ビルドする際にモジュールを導入しビルドする

cd ~/nginx-1.21.1
./confiure --with-http_v2_module
make
sudo make build

Nginxを起動

sudo /usr/local/nginx/sbin/nginx

curlでIndex.htmlが取得できる

curl --http2 localhost

別解

viなどのエディタでnginx.confを以下のように編集

listen 443 http2 -> listen 80

Nginxを起動

sudo /usr/local/nginx/sbin/nginx

curlでIndex.htmlが取得できる

curl --http2 localhost
 /
カテゴリー

概要

AくんはPython製のウェブアプリケーションフレームワークであるFlaskを使ってWEBサイトを構築している。Pythonのバージョン管理を行える pyenv を先輩から教えてもらったAくんはさっそく導入してみることにした。しかし、pyenvを導入してからWEBサーバが起動できなくなってしまった。

WEBサーバが起動できない原因が何であるか調査し、WEBサイトが表示できるように修正せよ。

前提条件

Webサーバを立ちあげようとすると以下のエラーがでる。

$ python3 app/index.py 
Traceback (most recent call last):
  File "app/index.py", line 1, in <module>
    from flask import Flask
ModuleNotFoundError: No module named 'flask'

初期状態

踏み台サーバから $ curl 192.168.7.1:5000 をしても応答がない。

終了状態

踏み台サーバから $ curl 192.168.7.1:5000 をするとステータスコード200のレスポンスが返ってくる。

解説

pyenvをインストールしglobalがsystem以外のパス(/home/user/.pyenv/shims/python3)に設定された場合、もともと使っていたsite-packagesを参照できなくなるのが原因でした。

解法はいくつかあり

  • pip install flask コマンドでFlaskをインストールする
  • pyenvのパスを解除し元のsite-packagesを参照できるようにする
  • pyenv global を解除する

といった方法があります。

 /
カテゴリー

概要

とある会社に勤めている、K君はサーバのお天気管理システムを開発しています。しかし、気温と湿度の情報を取得・送信することができません。原因を究明して取得・送信出来るようにして下さい。

前提条件

  • client/etc/hostsを変更しない

初期状態

  • prob4-proxyからwebとapiにリバースプロキシをしている。
  • VNCのFirefoxからhttp://web.testにアクセスし、気温と湿度を取得・送信しようとするが送信できない。
  • apiサーバの/srv/api/以下にexpressサーバの設定が記述されている。これらはnpm startで起動できる。

終了状態

  • VNCのFirefoxからhttp://web.testにアクセスし気温と湿度を取得・送信ができ、リソースが更新される。
  • prob4-apiのOSを再起動してもexpressサーバが自動で起動されているようになっている。

解説

この問題ではAPIサーバから取得する情報にCORS設定に問題があったためにブラウザ側でブロックされるのが原因でした。Proxyサーバに適切なCORSヘッダーを追加する設定を追加することで、正しくAPIサーバからリソースを取得することができる様になります。

CORS(Cross-Origin Resource Sharing)とは

自分とは異なるオリジンにリソースをリクエストするときにオリジン間リクエストが発生する。
セキュリティ上の都合のためブラウザはスクリプトから発生するオリジン間リクエストを制限しています。

同じオリジンからのリソース取得だけでは不便なので、異なるオリジンからWebサイトに対してのアクセスを可能をする仕組みがCORS設定です。今回はこの設定が間違っていました。

参考

オリジン間リソース共有 (CORS) – HTTP | MDN – Mozilla

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

Origin (オリジン) – MDN Web Docs 用語集

https://developer.mozilla.org/ja/docs/Glossary/Origin

解法

工程①

APIにてexpressサーバを起動する

cd /srv/api
npm start

> [email protected] start /srv/api
> node server.js

server is listening on port 3000...

VNCに接続する。

web.testにアクセスし取得・送信ボタンを行うがリソースが取得・送信できないことが確認できる。

デベロッパーツールで通信を確認してみるとCORS Missing Allow Originと表示されるのでCORSが原因ということが分かる

OPTIONの方をクリックし、ヘッダーを比較すると以下のようなことが確認でき、一部の設定に間違いがあることが分かる。

問題文にProxyサーバとあることからProxyサーバでヘッダーを書き換えていると予想できる。

確認してみると、間違えていることが分かるのでviなどで正しく修正し、Nginxを再起動する。

sudo vim /etc/nginx/nginx.conf


~~~~省略~~~~~~

server {
          listen 80;
          server_name api.test;

          location / {
            proxy_pass http://192.168.4.102:3000;

            add_header Access-Control-Allow-Origin '*';

            # POST を追加
            add_header Access-Control-Allow-Methods 'GET, POST';

            # Acccept から content-type に変更
            add_header Access-Control-Allow-Headers 'content-type';
          }
        }

sudo systemctl restart nginx

web.testよりリソースが送信・取得できる。

工程②

prob4-apiのOSを再起動してもexpressサーバが自動で起動されているようになっている。とあるのでこれを行う。

viなどでサービスファイルを作成し自動起動を有効化することで終了条件を満たせる。なお別解としてcronなどでも起動できました。

sudo vim /etc/systemd/system/api.service

[Unit]
Description=express server
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/usr/bin/node /srv/api/server.js
WorkingDirectory=/srv/api
KillMode=process
Restart=always
User=user
Group=user

[Install]


sudo systemctl enable weather

その他

チームによってはヘッダーが二重についていることがあったが、終了条件を満たせていれば満点にしました。

 /
カテゴリー

概要

サーバーを勉強するためにおうちラックを買った先輩がKubernetesに手を出し始めたらしい。
Ingressを使って Webサイトを用意したところ、なぜかつながらないらしい。
原因を究明してつながるようにしてほしい。

前提条件

  • Ingressはnginx.ingress.kubernetes.io/proxy-bufferingをonにしたまま
  • はじめにデプロイされていたリソースを削除しない
  • デプロイされているPodを変更してはいけない

初期状態

  • 問題環境に接続するためのbastionサーバーから curl -k https://192.168.13.101 をすると、502が返ってくる 。

終了状態

手元のPCから curl -k https://192.168.13.101 をするとステータスコード200の以下のレスポンスが返ってくる。

welcome to ictsc2021 summer

解説

KubernetesのNginx Ingress に関する問題でした。

問題の初期状態

  • Kubeadmによって構築されたK8sクラスタにMetalLB、Nginx ingress Controller、Nginxがデプロイされている。
  • MetalLBはサンプル通り、[Nginx ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/#bare-metalはServiceをNodePortからLoadBalancerに変更したもの
  • そのほかのマニフェスト,利用したファイルは以下
    ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/proxy-buffering: "on"
    nginx.ingress.kubernetes.io/proxy-buffer-size: "8"
    kubernetes.io/ingress.allow-http: "false"
  name: nginx-ingress
spec:
  tls:
  - secretName: tls-secret
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number:  443

nginx.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 443
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/conf.d
        - name: tls-cert
          mountPath: /etc/nginx/tls
        - name: index-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx-conf
      - name: tls-cert
        secret:
          secretName: tls-secret
      - name: index-html
        configMap:
          name: index-html

index.html

welcome to ictsc2021 summer
  • curl -k https://192.168.13.101を問題環境に接続するための踏み台や K8sクラスタのVMから行うと、502 Bad Gatewayが返ってくる。

解答解説

ingress.yamlでnginx.ingress.kubernetes.io/proxy-buffer-size: "8"と指定されており、バックエンドからプロキシが受け取ることができるヘッダーサイズがとても小さくなっている。
また、Ingressがバックエンドの443番ポートにアクセスしているが、Nginx ingress controllerはデフォルトでHTTPを使うため、プロトコルの違いによってコンテンツが取得できない。

  • nginx.ingress.kubernetes.io/proxy-buffer-size が “8” から”256″や”8k”などコンテンツを配信できるバッファサイズに変更
  • nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"をannotationに追加
    することで解決できる。

その他

割と、PodのSVCに直接指定したIPアドレスを割り当てる解答がありましたが、Ingressを使う旨が問題文にあったので終了条件は満たしていますが減点しました。
また、Pod/PodのSVCは80で受け付けているので、backend-protocol アノテーションをつけなくても解答できることに今気づきました。

 /
カテゴリー

概要

名前解決をしてくれるコードを用意した。これを実際に使用した所うまくキャッシュを参照できていない様子。
DNSキャッシュサーバとしてsystemd-resolvedが動いているのだが、どうにかしてキャッシュを参照するようにしてほしい。

前提条件

  • ~/配下にresolve.c,resolveというファイルが存在するがこれを編集してはいけない。
  • /etc/resolv.conf に変更を加えてはならない。

初期状態

./resolver hoge.hogeを実行してもキャッシュサーバを参照してくれない。

終了状態

./resolver hoge.hogeを実行した時にキャッシュを参照してくれる。
キャッシュのヒット数などはresolvectl statisticsなどで確認できる。

解説

systemd-resolvedはDNSキャッシュサーバーです、resolver.cではgethostbyname()が利用されており、通常glibcはnsswitchを利用してgethostbyname()のバックエンドを切り替えるのですが、nsswitchがresolve(つまりnss_resolve.so)を読むような設定にしていないと、files(つまりnss_files.so)しかよみこまれないため、/etc/hostsへDNSリクエストをしてしまい、キャッシュが使えません。

回答例

・・・
group:       sss files systemd
hosts:      resolve files dns

services:   files sss
netgroup:   sss
・・・

このhostsの部分にresolveを書き加えることで、この問題は解決できます。
この並びにも意味が有り、左が参照される優先度が一番高く、右に行くほど優先度が低くなります。

講評

この問題で /run/systemd/resolve/stub-resolv.conf のシンボリックリンクを/etc/resolv.confに置き換えて回答している方がいましたが、これは「/etc/resolv.confに変更を加えてはならない。」という条件に抵触しているため、採点に影響させています。