ictsc2024-eds問題

問題名

インフラ勉強中・・・

概要

多誤君は、友人Aから譲り受けたサーバーを研究室に設置し、勉強用のサーバーとして活用しています。 そして、dockerとiptablesを使用して自分しか見れないwebサーバをで作成しました。しかし、サーバーにアクセスすると、意図しないページが表示される現象が発生しました。さらに、そのサーバーには他の研究室の端末からもアクセスできてしまい、意図したセキュリティ設定が反映されていないことが判明しました。

あなたは優しい友人Aです。

多誤君が抱えている問題を解決してあげましょう。

前提条件

  • 192.168.36.0/24の中でeds-client1(IPアドレス:192.168.36.2)以外からの8080 ポートへのTCPトラフィックをDROPすること。
  • /home/user/app/Dockerfileを使用し、8080 ポートに対するリクエストにはWelcome to ITSC2024!!という内容の応答を返すこと。
  • 報告書では発生していたトラブル、解決方法、解決理由などを明確に記載すること。
  • 制約

  • Dockerfileは変更不可。
  • Dockerネットワークを壊さないこと。
  • サーバー再起動後も終了状態が維持されること。
  • nginxなどでリバースプロキシを行ってはいけません。
    • つまり、特定のDocker コンテナが 8080 ポートで直接応答できるようにすることが求められています。
  • 初期状態

  • eds-client1192.168.36.2から$ curl http://192.168.36.1:8080を実行するとWelcome to ITSC2024?という内容が返却される
  • eds-client2192.168.36.3から$ curl http://192.168.36.1:8080を実行するとWelcome to ITSC2024?という内容が返却される
  • 終了状態

  • eds-client1192.168.36.2から$ curl http://192.168.36.1:8080を実行するとWelcome to ITSC2024!!という内容が返却される
  • eds-client2192.168.36.3から$ curl http://192.168.36.1:8080を実行するとCouldn't connect to serverとなる
  • 減点

  • iptablesを変更した場合、冗長なルールや不要なルールは排除すること。
  • ansible(ネタバレ)

    ---
    - name: 問題環境構築
      hosts: server
      become: true
      collections:
        - community.general
      vars:
        app_dir: /home/user/app
        docker_image_name: my-node-app
      tasks:
        - name: 必要なパッケージをインストール (docker.io, nginx, lsb-release, iptables-persistent)
          apt:
            name:
              - docker.io
              - nginx
              - lsb-release
              - iptables-persistent
            state: present
            update_cache: yes
    
        # =============== user作成 ===============
        - name: userユーザーのパスワードを変更する
          user:
            name: user
            password: "{{ 'ictsc2024' | password_hash('sha512') }}"
        # =============== ここまでuser作成 ===============
    
        # =============== ここからポート競合 && 誤字 ===============
        - name: Nginx の既定サイト設定を編集してポート8080で待ち受ける
          replace:
            path: /etc/nginx/sites-enabled/default
            regexp: 'listen\s+((?:\[::\]:)?)80(\s+default_server)?\s*;'
            replace: 'listen \g<1>8080\g<2>;'
          notify: Restart nginx
    
        - name: Nginx の既定サイト設定を置き換える
          copy:
            src: src/nginx/index.html
            dest: /var/www/html/index.html
            owner: root
            group: root
            mode: '0644'
          notify: Restart nginx
    
        - name: Nginx を起動・有効化する
          service:
            name: nginx
            state: started
            enabled: yes
    
        - name: Nginx を再起動する
          become: true
          service:
            name: nginx
            state: restarted
    
        # 確認
        - name: Nginx が 8080 で待ち受けているか確認
          command: curl -s http://localhost:8080
          register: result_8080
    
        - name: アプリケーション用ディレクトリを作成する
          file:
            path: "{{ app_dir }}"
            state: directory
            owner: user
            group: user
            mode: '0755'
    
        - name: Dockerfile を配置する (EXPOSE 8080 に変更)
          copy:
            src: src/app/Dockerfile
            dest: "{{ app_dir }}/Dockerfile"
            owner: user
            group: user
            mode: '0644'
            force: yes
    
        - name: server.js 配置する (ポート8080でリッスン)
          copy:
            src: src/app/server.js
            dest: "{{ app_dir }}/server.js"
            owner: user
            group: user
            mode: '0644'
            force: yes
    
        - name: package.json を配置する
          copy:
            src: src/app/package.json
            dest: "{{ app_dir }}/package.json"
            owner: user
            group: user
            mode: '0644'
    
        - name: Docker イメージをビルドする (EXPOSE 8080)
          docker_image:
            name: "{{ docker_image_name }}"
            tag: latest
            source: build
            build:
              path: "{{ app_dir }}"
    
        - name: Docker コンテナを起動する (ホスト8080:コンテナ8080, ポート競合で失敗するはず)
          docker_container:
            name: "{{ docker_image_name }}"
            image: "{{ docker_image_name }}:latest"
            state: started
            ports:
              - "8080:8080"
            auto_remove: yes
          register: docker_run_result
          ignore_errors: true
    
        - debug:
            msg: "Docker run 結果: {{ docker_run_result }}"
    
        # =============== ここまでポート競合 && 誤字 ===============
    
        # =============== ここからiptable ===============
        - name: パケット転送を有効にする
          sysctl:
            name: net.ipv4.ip_forward
            value: 1
            state: present
    
        - name: 192.168.36.2からのポート8080へのTCPトラフィックをACCEPT(最優先で挿入)
          ansible.builtin.iptables:
            chain: INPUT
            protocol: tcp
            source: 192.168.36.2
            destination_port: 8080
            jump: ACCEPT
            action: insert
            rule_num: 1
            state: present
          notify:
            - Save iptables rules
    
        - name: 192.168.36.0(意図的に/24を抜いている)からのポート8080へのTCPトラフィックをDROP(次に挿入)
          ansible.builtin.iptables:
            chain: INPUT
            protocol: tcp
            source: 192.168.36.0
            destination_port: 8080
            jump: DROP
            action: insert
            rule_num: 2
            state: present
          notify:
            - Save iptables rules
    
        - debug:
            var: iptables_status.stdout
        # =============== ここまでiptable ===============
    
      handlers:
        - name: Restart nginx
          service:
            name: nginx
            state: restarted
        - name: Save iptables rules
          become: true
          shell: iptables-save > /etc/iptables/rules.v4
    
    - name: パスワード変更
      hosts: ubuntu
      become: true
      tasks:
        - name: userユーザーのパスワードを変更する
          user:
            name: user
            password: "{{ 'ictsc2024' | password_hash('sha512') }}"
    ← Go home