夏休みの宿題でPort Scannerを自作してみた①〜技術選定編〜

## はじめに

こんにちは。
世間は夏休み真っ只中ですが、皆さんはいかがお過ごしでしょうか。
夏休みといえば、宿題がつきものですよね。
私は夏休みというと，なにか新しいことができそうな謎のワクワク感がするタイプなので，なんか作ってみるかということで，Port Scannerを自作してみました。
みなさんもぜひ，夏休みの宿題としてPort Scannerを自作してみてはいかがでしょうか。

本記事では鋭意作成中の[my_portscanner](https://github.com/RyosukeDTomita/my_portscanner)を作る過程を紹介していきます。
よりよりものにしていきたいので，みなさんのアドバイスやコメントもお待ちしております。  

---

## Port Scannerとは

> 参考: [ポートスキャナとは](https://wa3.i-3-i.info/word14947.html)

Port Scannerとは、ネットワーク上のコンピュータに対して、どのポートが開いているかを調べるツールです。
サーバーは使用しているサービスに応じて、特定のポートを使用して通信しているため，どのポートが空いているかを調べることで、そのサーバーがどのようなサービスを提供しているかを知ることができます。
攻撃者が攻撃の最初にPort Scannerを実行し、どのポートが開いているかを調べ、攻撃の足がかりを探ることがあります。

### 注意すること Port Scannerの実行について

Port Scanner自体は悪意のあるソフトウェアではありません。ですが，他人のサーバーに対して許可なくPort Scannerを実行することは避けるべきです。なぜなら，Port Scanの際に対象のサーバに負荷がかかってしまい，サービスが停止する可能性があるからです。場合によっては法律に抵触する可能性もありますので，自分の管理下にあるサーバーに対してのみPort Scannerを実行するようにしましょう。

---

## なぜPort Scannerを自作するのか〜Port Scannerから学べること〜

Port Scannerというと，セキュリティエンジニアの使う道具というイメージが強いですが，実はPort Scannerを自作することで，ネットワークの仕組みも学ぶことができます。
基本的なPort Scannerは3way handshakeというネットワークの基本的な仕組みを使ってポートのステータスを調べています。このあたりの仕組みを自分で手を動かして学ぶことができるので，ネットワークの基礎を学ぶのにもってこいの教材です。
また，動作の仕組み自体は結構シンプルなのである程度動くものはすぐに作れるので，成果が出やすくこの夏なにか作りたいという欲求を満たすことができます。さらに，結構カスタマイズする余地が残されているので，楽しくなってきたら，新しい機能をどんどん追加できます。

このように，

- プログラミング技術が向上する
- ネットワークの基礎が手を動かしながら学べる
- 夏休みになにかやったという成果がそこそこ簡単に得られる。
ことから夏休みの宿題としてPort Scannerはピッタリなのです。

---

## 技術選定

まず，どのPort Scannerを自作するにあたってどのような技術を使うかを考えました。
そのため，まず，代表的なPort Scannerについて調べてみました。

### 既存のPort Scanner

#### nmap

Port Scannrの有名どころといえば，やはり[nmap](https://github.com/nmap/nmap)です。nmapはPort Scannerの中でもデファクトスタンダードといえるツールで，多くの機能を持っています。nmapはC，Lua，C++で主に書かれています。

#### masscan

自分は[massscan](https://github.com/robertdavidgraham/masscan)は使ったことはないですが，歴史のあるPort Scannerの一つです。masscanはほぼ100%Cで書かれています。

#### zmap

- [zmap](https://github.com/zmap/zmap)は，インターネット全体をスキャンすることができるPort Scannerです。zmapもほとんどCで書かれています。

#### rustscan

最近では，名前の通りRustで書かれた[rsutscan](https://github.com/RustScan/RustScan)が注目されています。rustscanは高速で，nmapよりも高速にPort Scanを行うことができ，docker等のモダンな技術を開発環境に取り入れています。

### 目指すべきPort Scannerのポイントを絞り込む

手を動かす前に一旦，今回の作成の目的を整理しました。

- なるべくこの夏中に完成させたい --> 自分が慣れ親しんだ言語でのほうが良さそう。
- 実行速度の優先度は高くない。
- Pythonにはnmapのライブラリがあるが，面白くないのでなるべく処理を自分で書きたい。
- パット見でポートスキャンの処理をみて仕組みがわかるようなシンプルなものにしたい。

ということで，今回はPythonを使ってPort Scannerを作成することにしました。Pythonを選んだ理由としては，
    - 個人的に慣れ親しんだ言語であること
    - ネットワーク系のライブラリ(Scapyやsocket等)が豊富であること
    - asyncioを使った並行処理にもチャレンジすることである程度の高速化が見込めること
が理由です。

### 開発環境の技術選定

Python製のツールを実行するうえで，どのような環境で実行するかも考えました。

#### パッケージマネージャ

パッケージマネージャは[**rye**](https://rye.astral.sh/)を使うことにしました。
ryeはpipと違い，ライブラリのバージョン管理がしやすく，シンプルで軽量，キャッシュを利用してインストール時間を短縮できるという特徴があります。
poetry等のパッケージマネージャもありますが，poetryは少し触ったことがあったので，言語選びで冒険しなかった分，最もナウでヤングでイケてそうなryeに挑戦しようかなと笑。

~~あとからpoetryにしておけば良かったと若干後悔する瞬間がきましたが~~rye最高!!

#### 実行環境

作ったものを友人や知人に触ってもらえたらいいなと思ったので，配布のしやすさを考えて，**Docker**を使うことにしました。
また，最近ずっといじっている**Dev Container**を実際の開発でつかってみることにしました。
Dev ContainerはVSCodeの拡張機能で，Dockerコンテナ内で中でVSCodeを開くことができ，

- Dockerfileを汚さずにコンテナにツールをインストールできる
- Extensionsの管理も.devcontaienr/devcontainer.jsonで行えるので，開発環境の共有がしやすい
- プロジェクトごとに環境を切り替えられるのでVSCodeが拡張機能だらけになりくにい
といった開発環境まるごと管理できる便利ツールです。
本記事では，Dev Containerについてこれ以上の深堀りはしませんが，興味がある方は，自分の作った[Dev Container学習用リポジトリ](https://github.com/RyosukeDTomita/devcontainer-test)や，[夏休みの自由研究: Dev Containerによる開発環境コンテナ化](https://zenn.dev/sigma_tom/articles/7ee1915d5c414b)を読んでみてください。

#### ライブラリ

ライブラリはおおまかに，[**socket**](https://docs.python.org/ja/3/library/socket.html)や[**Scapy**](https://scapy.readthedocs.io/en/latest/introduction.html)**を使うだろうなと思いましたが，それ以外は適宜いれていくことにしました。

#### FormatterとLinter

- Formatterは**black**を使うことにしました。blackはPythonのコードフォーマッタで，自動でコードを整形してくれるので，コードに統一感が出て見やすくなります。
- linterは**flake8**を使うことにしました。flake8はPythonの静的解析ツールで，コードの品質をチェックしてVSCode上で問題のある部分をハイライトしてくれます。

どちらもpep8というコーディング規約に準拠しているので，pep8に準拠したコードを書くのが容易になります。

---

## TO BE CONTINUED

次回は，実際にPort Scannerを作成しつつ，どういう構成にするか考える[**設計編**](https://qiita.com/sigma_devsecops/items/fe2b30a220f981486612)をお送りします。