IPv6のみのサーバーへIPv4からでもアクセスする方法(OCI経由)

IPv6のみのサーバーへIPv4からでもアクセスする方法(OCI経由)
Photo by Conny Schneider / Unsplash

概要

自宅はドコモ光10Gbのインターネットを使用しているので、IPv6アドレスからしかアクセスできません。
これだと、自宅のサーバー上にNextcloudを稼働させていますが、非常に不便なのでオラクルクラウド経由でIPv4からでもアクセスできるように設定しました。

構成

IPv4網 → Oracle Cloud【nginx(リバースプロキシ) → WireGuard VPN】
→ IPv6網 → 自宅サーバー【WireGuard VPN → Nextcloud】

WireGuard経由でのアクセスを採用した理由

  • 速い(カーネル実装 / UDP ベース)
  • 設定がとてもシンプル
  • IPv4 ↔ IPv6 のブリッジングに強い
  • セキュリティが強固(最新暗号)
  • Oracle Linux 8 でも標準対応

私のOracle Clound では、下記の構成のインスタンスを使っています。

項目 内容
OS Oracle Linux 8.1
Shape VM.Standard.A1.Flex
OCPU count 1
Network bandwidth (Gbps) 1
Memory (GB) 6
Local disk Block storage only

WireGuard VPNのトンネルネットワークを10.10.0.0/24として構築します。
OCI : 10.10.0.1
自宅:10.10.0.2

手順

【OCI側 Oracle Linux 8】
(1) wireguardをインストールする
$ sudo dnf insall -y wireguard-tools

(2) 公開鍵ペアを作成する
$ wg genkey | tee server_private.key | wg pubkey > server_public.key

  • wgはwireguardの略
  • wg genkeyは秘密鍵を作成する
  • teewg genkeyの結果を標準出力に渡す(ここではwg pubkeyに渡す)とともに、server_private.keyに保存する
  • wg pubkeyはteeコマンドで受け取った秘密鍵から公開鍵を作成し、server_public.keyに保存する

【自宅サーバー側 Ubuntu 22.04】
(3) wireguardをインストールする
$ sudo apt install wireguard-tools

(4) 公開鍵ペアを作成する
$ wg genkey | tee nextcloud_private.key | wg pubkey > nextcloud_public.key

【OCI側 Oracle Linux 8】
(5) /etc/wireguard/wg0.confを作成する

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = (server_private.key の内容)

# NATして自宅LANに戻せるようにする
PostUp   = firewall-cmd --add-masquerade && firewall-cmd --zone=public --add-port=51820/udp
PostDown = firewall-cmd --remove-masquerade && firewall-cmd --zone=public --remove-port=51820/udp

[Peer]
# 自宅側
PublicKey = (nextcloud_public.key の内容)
AllowedIPs = 10.10.0.2/32, 192.168.1.0/24

(6) IP転送を有効化する

$ sudo bash -c 'echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wg.conf'
$ sudo sysctl --system

(7) (5)で作成したwg0を起動する
$ sudo systemctl enable --now wg-quick@wg0
$ sudo wg
interface: wg0
public key: 9Ab7o0LyajPXKMvFShZlPuUZyJ6Q/ts0bm+LdfquEQ0=
private key: (hidden)
listening port: 51820

peer: s2555huz863rgW4cIn85OKiJbPwBWbMMrQfSXfZSWS0=
allowed ips: 10.10.0.2/32, 192.168.1.0/24

【自宅サーバー側 Ubuntu 22.04】
(8) /etc/wireguard/wg0.conf を作成する

[Interface]
Address = 10.10.0.2/24
PrivateKey = (nextcloud_private.key)
DNS = 8.8.8.8

[Peer]
PublicKey = (server_public.key)
Endpoint = (OCIのパブリックIPv4アドレス):51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

(9) wg0 を起動

$ sudo systemctl enable --now wg-quick@wg0
$ sudo wg
interface: wg0
  public key: s2555huz863rgW4cIn85OKiJbPwBWbMMrQfSXfZSWS0=
  private key: (hidden)
  listening port: 40949
  fwmark: 0xca6c

peer: 9Ab7o0LyajPXKMvFShZlPuUZyJ6Q/ts0bm+LdfquEQ0=
  endpoint: 158.101.157.243:51820
  allowed ips: 0.0.0.0/0, ::/0
  transfer: 0 B received, 148 B sent
  persistent keepalive: every 25 seconds

(10) 自宅のルータのフィルタリングルールで、UDPの51820ポートを通過するように設定

【OCI側 Oracle Linux 8】
(11) OCI側のSecurity ListのIngress RulesにUDPの51820ポートを通過するように設定

(12) OCI側から自宅サーバー(10.10.0.2)にpingが打てることを確認

$ ping 10.10.0.2
PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data.
64 bytes from 10.10.0.2: icmp_seq=1 ttl=64 time=10.9 ms
64 bytes from 10.10.0.2: icmp_seq=2 ttl=64 time=10.9 ms
64 bytes from 10.10.0.2: icmp_seq=3 ttl=64 time=10.6 ms

【自宅サーバー側 Ubuntu 22.04】
(13) 自宅サーバー側からOCI側(10.10.0.1)にpingが打てることを確認

$ ping 10.10.0.1
PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_seq=1 ttl=64 time=17.7 ms
64 bytes from 10.10.0.1: icmp_seq=2 ttl=64 time=10.5 ms
64 bytes from 10.10.0.1: icmp_seq=3 ttl=64 time=10.8 ms

【OCI側 Oracle Linux 8】
(14) Nginxでリバースプロキシの設定
/etc/nginx/sites-available/abc.ddns.net.conf

upstream nextcloud_backend {
    server 10.10.0.2:443;
}

server {
    server_name 89wa.ddns.net;

    # ★ ACME チャレンジは OCI で直接返す
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        proxy_pass https://nextcloud_backend;
        proxy_set_header Host 89wa.ddns.net;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_ssl_server_name on;
        proxy_ssl_name nextcloud.local;
    }
}
  • Wireguard VPN内で暗号化されているので、HTTPS(443)で転送する必要はなく、HTTP(80)で転送すればよいのですが、今回はNextcloudがHTTPS接続を前提としているため、あえてHTTPS接続にしました。
  • proxy_ssl_name nextcloud.localの部分は、後で自宅サーバー上で証明書を作成します。

設定ができたら、

$ sudo nginx -t
$ sudo systemctl restart nginx

を実行します。

(15) abc.ddns.netがOCIのNginxに行くように、動的DNSを設定

(16) Let's Encrypt を使ってHTTPS化

Let's Encryptは証明書更新のときに、
https://abc.ddns.net/.well-known/acme-challenge/XXXX
あるいは http://abc.ddns.net/.well-known/acme-challenge/XXXX
にアクセスして「認証用ファイル」が正しく返ってくるかを確認します(HTTP-01 チャレンジ)。

なので、ACME用のパスは転送するのではなく、OCIで処理する設定をabc.ddns.net.confに入れています。

    # ★ ACME チャレンジは OCI で直接返す
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

あとは、/var/www/certbotのディレクトリを作成し、nginxから読み書きできるようにします。

sudo mkdir -p /var/www/certbot
sudo chown -R nginx:nginx /var/www/certbot

ここまでできたら、証明書をインストールします。

sudo dnf install -y certbot python3-certbot-nginx (インストールしていなければ)
sudo certbot --nginx -d abc.ddns.net

CertbotはIPv4の設定しか追加しないので、
abc.ddns.net.confの設定にIPv6の設定を追加します。

upstream nextcloud_backend {
    server 10.10.0.2:443;
}

server {
    server_name abc.ddns.net;

    # ★ ACME チャレンジは OCI で直接返す
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        proxy_pass https://nextcloud_backend;
        proxy_set_header Host abc.ddns.net;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_ssl_server_name on;
        proxy_ssl_name nextcloud.local;
    }

    listen 443 ssl http2; # managed by Certbot
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/abc.ddns.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/abc.ddns.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}



server {
    listen 80;
    listen [::]:80;
    server_name abc.ddns.net;

    # ★ HTTP でも ACME 用の場所は用意しておくと安心
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    # それ以外は HTTPS にリダイレクト
    location / {
        return 301 https://$host$request_uri;
    }

}
~    

(17) 自宅のNextcloudの設定変更(config.php)
下記を追加します。

  'trusted_proxies' => 
  array (
    0 => '10.10.0.1',
  ),

設定が終わったらApacheを再起動します。

(18) オレオレ証明書を作成します。

sudo mkdir -p /etc/ssl/nextcloud
sudo openssl req -x509 -newkey rsa:4096 \
  -keyout /etc/ssl/nextcloud/nextcloud.key \
  -out /etc/ssl/nextcloud/nextcloud.crt \
  -days 3650 -nodes \
  -subj "/CN=nextcloud.local"

  • OCIから自宅サーバーへは、Wireguard経由のHTTPS接続でしか使用しないため、オレオレ証明書で問題ありません。

(19) 接続確認

ブラウザからabc.ddns.netにアクセスします。

やりました!
今回はちょっと苦労しましたぁ。

残りの作業として、今まで自宅のサーバーに直接アクセスしていたので、ルーターのフィルタリングルールに、自宅サーバーへの直アクセスができない設定を入れたりしました。