Ubuntu Weekly Recipe

第617回 SOCKSを利用してSSHのみで簡易VPNを構築する

この記事を読むのに必要な時間:およそ 4 分

リモートワークを行う際に俎上に載る問題のひとつが「プライベートネットワークにある組織内リソースにどのようにアクセスするか」です。今回はそんな問題の解決策のひとつとなりうる,SSH経由でSOCKSプロキシを構築する方法を紹介しましょう。

HTTP/HTTPSが使えるVPN(のようなもの)がほしい

ここからいろいろ述べますが,簡単に言うと「SSHのDynamic Port ForwardingをSOCKSプロキシとして利用する」というだけの話です。

さて,リモートワークによる働き方は,会社の文化・セキュリティ要件によって多種多様に分かれます。その中でも最も「ゆるい」のが,⁠個人の端末・インターネット回線を用いてあとは良しなにやってくれ」というものでしょう。作業がインターネット上で完結する,つまりパブリックなクラウドサービスを積極的に活用している業務であれば,それでもおおよそなんとかなります。

しかしながらそうでない場合は,何かにつけてプライベートネットワークである組織内LAN上のリソースにアクセスしなければなりません。そこで出てくるのがリモートデスクトップとVPNという概念です。リモートデスクトップはまず組織内LAN上に存在するPCに接続した上で,あとはそのPCから組織内リソースにアクセスします。つまりデータが社外ネットワークに出ることはないので比較的安全です※1⁠。ただし「デスクトップ画面」をネットワーク上でやりとりするため,データ上の効率はあまりよくありません。社員の多くがVPNを利用することになって眠れない夜を過ごしているインフラエンジニアも多いことでしょう。また,組織内LAN上のPCにどのように接続するのか,経路をどう安全に保つのかという別の問題もあります。

※1
映像データとしてレンダリングされたものがクライアントPCに表示されるため,厳密には情報が社外ネットワークに出ています。

リモートデスクトップに代わる案のひとつがVPN(Virtual Private Network)です。手元にあるPCをインターネット経由で組織内LANに接続する方式です。リモートデスクトップに対してネットワークに流れるデータは少なくなるかどうかは使い方に依存します。たとえばオフィス系ソフトウェアの編集がメインであれば,一度ファイルをダウンロードした上でローカルで編集すれば良いことになるので,流れるデータは大きく削減できるでしょう。ただし社外ネットワークの外にあるPCにデータをダウンロードするため,組織内のセキュリティルールとの整合性を取ることが難しくなります。もちろんVPN経由でリモートデスクトップを使うことも一般的です。

本連載ではこれまで次の記事で,リモートデスクトップ方式,VPN方式にそれぞれ使えるソフトウェアを紹介してきました。

今回はそれに対して,⁠SSHを用いて組織内LAN内部のウェブリソースにアクセスする方法」を紹介しましょう。

組織内リソースが「HTTP/HTTPSでアクセスできるもので統一されている」というケースはそれなりに存在するかと思います。SMBに依存しているケースなど,100%そうなっていることはなかなかないのかもしれませんが,リモートワークを行う上で必要なものだけであればおおよそウェブブラウザーで完結するケースはそれなりに高そうです。本連載の読者であれば,組織内WikiやGitLab/Redmineをはじめとするチケット管理システムあたりさえ見られれば仕事ができることも多いのではないでしょうか※2⁠。

※2
そのSMBによるファイル共有もNextcloudなどに移行してくれれば今回紹介する方法が使えるのですが,それは高望みしすぎなのかもしれません。

モダンなウェブブラウザーであれば,SOCKSプロキシに対応しています。さらにSSHのDynamic Port Forwardingを用いれば,SSHコマンドをSOCKSサーバーにできます。つまりウェブブラウザー側で特定のアドレスのみSOCKSプロキシを使うように設定すれば,インターネット上のサイトと組織内LAN上のサイトの双方にその違いを意識することなくアクセスできるようになるわけです。

テスト用の隔離ネットワークサイトの作成

まずはテスト用に隔離されたネットワーク上のサイトを作成しましょう。方法はいくつか存在します。その中でも一番簡単なのはローカルからしかアクセスできないウェブサーバーが動いているマシンを作ることです。今回はLXDを使ってはいるものの,もちろんVirtualBoxでもmultipassでもかまいません。

$ lxc launch ubuntu:20.04 lts
$ lxc exec lts -- sh -c "apt update && apt full-upgrade -y && apt autoremove -y"
$ lxc exec lts -- sh -c "apt install nginx -y"

ホストから見たコンテナのアドレスが「10.93.9.120」だとすると,コンテナの外からNginxのテストサイトにアクセスできます。

$ curl -sL http://10.93.9.120/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
(以下略)

これをコンテナの外からはアクセスできず,コンテナの中からのみアクセスするようにします。手っ取り早いのはufwでフィルタリングしてしまうことです。ここではすべてフィルタリングしてしまいましょう。

$ lxc exec lts -- ufw default deny
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
$ lxc exec lts -- ufw enable
Firewall is active and enabled on system startup
$ lxc exec lts -- ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

これでコンテナの外からはアクセスできなくなりました。

$ curl -L http://10.93.9.120/
curl: (28) Failed to connect to 10.93.9.120 port 80: 接続がタイムアウトしました

このままだとコンテナ内部にSSHでログインできないので,それは許可しておきましょう。

$ lxc exec lts -- ufw allow ssh
Rule added
Rule added (v6)

SSHでコンテナ内部にログインすれば,サイトが閲覧できることも確認しておきます。

$ ssh ubuntu@10.93.9.120 curl -sL http://localhost/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
(以下略)

このコンテナのネットワーク(10.93.9.0/24)を,今回は組織内LANとみなします。つまりコンテナの外にあるマシンから,コンテナ内部のサイトを閲覧することが目標となります。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。