Gatsby Logo

VirtualBoxは80番や443番などのウェルノウンポートを握れない

2019-02-18

このタイトルには語弊があるので先に訂正しておくと、ウェルノウンポートを握れないわけではありません。しかし、それには特権ユーザーにてVirtualBoxを実行する必要があります。その理由を書いていきます。

事の背景はmacOS上でVirtualBoxを実行し、VM(Ubuntu18.04)上で動いているWebサーバ(Dockerコンテナ)に80番と443番をポートフォワーディングしようとしたことでした。通信経路は以下のようになると思います。

インターネット -> macOS -> VirtualBox -> Webサーバ

環境構築はPackerで行い、吐き出されたovaファイルをVitualBoxでインポートして実行してみた所、Webサーバにアクセスできません。VM内でcurlをlocalhost宛に叩いたらちゃんとDockerコンテナのWebサーバからレスポンスは返ってきます。しかし、macOS上でcurlをlocalhost向けに叩いてもConnection refusedでレスポンスがありません。ポートフォワーディング自体はちゃんと機能していて、プロビジョニング時に以下のようなコマンドを実行しています。

VBoxManage controlvm "vm-name" natpf1 "SSH,tcp,127.0.0.1,2222,,22"
VBoxManage controlvm "vm-name" natpf1 "HTTP,tcp,,80,,80"
VBoxManage controlvm "vm-name" natpf1 "HTTPS,tcp,,443,,443"

実際SSHはちゃんと機能しますし、VirtualBoxのUI上でもこの設定は反映されています。設定を全て削除し、UI上で設定を試みてみましたが、特にエラーが出ることもなく設定は完了するにもかかわらず、やはりアクセスすることが出来ません。VMのファイアウォールが閉じているわけでもありませんでした。lsofコマンドで確認した所、SSHのポートは取れているのに80番と443番は取れていませんでした。 数時間粘ってわからなかったので、先生に聞いてみた所、小一時間悩んで解決しました。

「ウェルノウンポートは特権ユーザーじゃないと握れないよ」

最初、自分の状況説明を受けて先生がわからなかったのはVirtualBoxのポートフォワーディングがipchainsで行われていると考られたからのようです。ポートフォワーディング自体はこちらの方が速いそうです。

なぜウェルノウンポートは特権ユーザーしか握れないのか、その理由は他人のサーバをすり替えることが出来てしまうからです。 例えばユーザーAとユーザーBがいるVM上で、ユーザーAがWebサーバを建てていたとします。この状態で通常ユーザーでもウェルノウンポートを握れてしまうとどうなるかというと、ユーザーBがDoS攻撃などでユーザーAのWebサーバを一時的にでも落としてしまえば、その瞬間に自分のWebサーバを上げることが可能になってしまいます。これを防ぐためにUnix系OSでは一般的に特権ユーザーでないと0-1023番のウェルノウンポートを取れないようにしています。

従って、VirtualBoxを特権ユーザーで実行すれば可能でした。しかし、sudo open /Applications/VirtualBox.appでは駄目なようで、sudo /Applications/VirtualBox.app/Contents/MacOS/VirtualBoxのようにバイナリを直接実行しなければいけないようです。ちなみにUIを開かなくて良いのなら以下のようにしてVMのインポートとスタートを行うことが可能です。

sudo VBoxManage import vm-name.ova
sudo VBoxManage startvm vm-name

これで実行すれば80番や443番にアクセスすることが可能になりました。

Docker Desktopなどはインストールする時に特権許可を求められますけどVirtualBoxはそんなことはありません。特権なしにポートフォワーディングしようとするとipchainsは使えないのでポートを握るしかありません。逆に言えば、特権を持っていなくても仮想マシンを実行できるということです。この利点でもあり欠点でもある特徴が今回自分を悩ませました。 ちなみに先生曰く、特権を握らずにポートフォワーディングする方法もあるそうで、

  • Apacheなどでリバースプロキシを80:8080のように張って、VirtualBoxでは8080:80のようにポートフォワーディング設定を行い転送をする
  • SSHのポートフォワーディング機能を使って80を8080に飛ばし、VirtualBoxでは8080:80のようにポートフォワーディング設定を行い転送をする

このようにすれば特権を取らなくても可能です。ちょっと冗長になるので今回はsudoで行いますが、macOSであればデフォルトでApacheやSSHが入ってますし、これも良いかもしれません。 一番悪いのはポートを取れないくせに設定の際に何も言わないVirtualBoxですけどね!!


参考