はじめに

我が家には数年前に組んだ「GeForce RTX 3080搭載のゲーミングPC」があるわけですが、最近はPCゲームをそこまでやらず、それなりのGPUあるのにもったいないなという状態です。

最近はローカルLLMの性能も良くなり、せっかくなのでそれなりのGPU積んだゲーミングPCをAIマシンにして有効活用できないかな、と思い。それなら自宅以外、クラウドからも呼び出せると嬉しいだろうなーと妄想してました。

そのはじめの一歩として、IPSec VPNで自宅ネットワークとGoogle Cloud VPCを繋ぐ仕組みを整えてみました。そのログです。

Overview

全体イメージはこちら。Google Cloudのほうはとりあえず疎通確認のためにCompute Engineのみ。自宅のほうはYAMAHAルータを中心にネットワークを構築してみてます。

Overview

自宅ネットワークの刷新

自宅の回線はNuro光で、今までZTE F660Aという端末にONU、ルータ、Wi-Fiアクセスポイントすべての役割を任せていました。 Google Cloudとの拠点間VPNをセットアップするためにはIPSecを用いたVPNに対応したルータが必要で、F660Aはそれには対応しておりません。というか家庭向けルータはIPSec VPNに対応しているほうが珍しいです。

そこで界隈では名高い業務用ルータ、YAMAHA製のルータに手を出してみることにしました。なんとなく憧れがあったので良い機会です。

入手したのはこちらRTX830。希望小売価格なんと101,200円(税込)! …この値段だと流石にな、とは思いましたが、メルカリで探すと中古2万円程度の出品がたくさんあったので購入。業務用の安定高機能なルータが2万はお買い得な気がします。

ルータが到着して、いざ設定開始。F660AはONU機能のみに限定、ルーティングはすべてRTX830のほうで行ってもらうようにしました。 このあたりの設定は先人のログがたくさん見つかったので参考にさせていただきました。

やったことまとめるとざっくり↓

  • F660A/LANとRTX830/WANをつなぐ
  • F660Aの管理画面にて
    • Wi-FiはOFF、DHCPもOFF
    • RTX830をMACアドレス指定で192.168.1.2にIP固定
    • DMZを設定してすべてのIPパケットがRTX830に届くように
  • RTX830の管理画面にて
    • プロバイダー接続で、以下の設定に
      • 接続種別: DHCP 、または固定IPアドレスによる接続
      • インターフェース: WAN

また、Wi-FiアクセスポイントのためにAterm WX1500HPを購入、ブリッジモードでセットしました。

以上が自宅ネットワークの刷新です。

ついでに、ネットワーク途切れる問題も解決したっぽい。

VPNの設定

それでは本題、VPNの設定です。拠点間VPNというもので、その中でも現代で主流なIPSecを用いることにします。

IPSec通信を行うために、

  • グローバルIP固定 or DDNS設定
  • IKEv2(鍵交換・認証のためのプロトコル)の諸々の認証設定、ポートフォワーディング設定

などの設定が必要になります。

まずは自宅ネットワークのRTX830側から。YAMAHAルータにはネットボランチDNSサービスという、動的にグローバルIPが変化してしまう環境でもホストアドレスを固定できるDDNSサービスがあるのですが、調べる限りNuro回線扱うこの構成だと利用できない模様。

ただ調べた感じ、我が家のNuro回線はほぼグローバルIPが変化していなさそうなので、とりあえずそのまま使うことにしました。DDNSもCloudflare DNSのAPI使えば実現できそうでした。

設定はRTX830のGUIでもできそうに見えましたが、IKEv2に対応した設定ができなさそうだったのでコマンドで設定。

こちらの書籍と、

これらページを参考にしました。

ざっくりこんな感じの設定になりました。

ip filter 201000 pass * 192.168.100.1 esp
ip filter 201001 pass * 192.168.100.1 udp * 500
ip filter 201002 pass * 192.168.100.1 udp * 4500
ip lan2 secure filter in {もともと存在ししていたフィルタ} 201000 201001 201002

tunnel select 1
 description tunnel my-tunnel
 ipsec tunnel 1
  ipsec sa policy 1 1 esp aes256-cbc sha256-hmac
  ipsec ike version 1 2
  ipsec ike always-on 1 on
  ipsec ike encryption 1 aes256-cbc
  ipsec ike group 1 modp2048
  ipsec ike hash 1 sha256
  ipsec ike keepalive log 1 on
  ipsec ike keepalive use 1 on rfc4306
  ipsec ike local address 1 192.168.100.1
  ipsec ike local name 1 {自宅ネットワークのグローバルIP} ipv4-addr
  ipsec ike nat-traversal 1 on
  ipsec ike pfs 1 on
  ipsec ike pre-shared-key 1 text {事前共有キー}
  ipsec ike remote address 1 {Google CloudのグローバルIP}
  ipsec ike remote name 1 {Google CloudのグローバルIP} ipv4-addr
 ip tunnel tcp mss limit auto
tunnel enable 1
ipsec auto refresh on
ipsec ike mode-cfg address pool 1 192.168.100.200-192.168.100.215/24

nat descriptor type 200 masquerade
nat descriptor address outer 200 primary
nat descriptor masquerade static 200 1 192.168.100.1 esp
nat descriptor masquerade static 200 2 192.168.100.1 udp 500
nat descriptor masquerade static 200 3 192.168.100.1 udp 4500

次にGoogle CloudのCloud VPNの設定。Cloud VPNには「高可用性(HA)VPN」と「Classic VPN」がありますが、個人で扱うものなので安価でシンプルな「Classic VPN」を採用します。

Cloud VPN の概要  |  Google Cloud

Terraformで設定した例が以下の通り。VPC、グローバルIPは別途用意してvariableとして渡す前提です。

# VPCのID
variable "network" {
  type    = string
}

# 事前共有キー
variable "vpn_tunnel_shared_secret" {
  type    = string
}

# 自宅ネットワークのグローバルIP
variable "vpn_home_ip" {
  type    = string
}

# Google CloudのグローバルIP
variable "vpn_static_ip" {
  type    = string
}

resource "google_compute_vpn_gateway" "vpn_gateway" {
  name    = "my-vpn-gateway"
  network = var.network
}

resource "google_compute_vpn_tunnel" "vpn_tunnel" {
  ike_version                     = "2"
  local_traffic_selector          = ["192.168.200.0/24"]
  name                            = "my-tunnel"
  peer_external_gateway_interface = "0"
  peer_ip                         = var.vpn_home_ip
  remote_traffic_selector         = ["192.168.100.0/24"]
  target_vpn_gateway              = google_compute_vpn_gateway.vpn_gateway.self_link
  vpn_gateway_interface           = "0"
  shared_secret                   = var.vpn_tunnel_shared_secret

  depends_on = [
    google_compute_forwarding_rule.allow-esp,
    google_compute_forwarding_rule.allow-udp4500,
    google_compute_forwarding_rule.allow-udp500,
  ]
}

resource "google_compute_route" "vpn_route" {
  dest_range          = "192.168.100.0/24"
  name                = "my-tunnel-route-1"
  network             = var.network
  next_hop_vpn_tunnel = google_compute_vpn_tunnel.vpn_tunnel.self_link
  priority            = "1000"
}

resource "google_compute_forwarding_rule" "allow_esp" {
  all_ports              = "false"
  allow_global_access    = "false"
  ip_address             = var.vpn_static_ip
  ip_protocol            = "ESP"
  is_mirroring_collector = "false"
  load_balancing_scheme  = "EXTERNAL"
  name                   = "my-rule-esp"
  network_tier           = "PREMIUM"
  target                 = google_compute_vpn_gateway.vpn_gateway.self_link
}

resource "google_compute_forwarding_rule" "allow_udp4500" {
  all_ports              = "false"
  allow_global_access    = "false"
  ip_address             = var.vpn_static_ip
  ip_protocol            = "UDP"
  is_mirroring_collector = "false"
  load_balancing_scheme  = "EXTERNAL"
  name                   = "my-rule-udp4500"
  network_tier           = "PREMIUM"
  port_range             = "4500-4500"
  target                 = google_compute_vpn_gateway.vpn_gateway.self_link
}

resource "google_compute_forwarding_rule" "allow_udp500" {
  all_ports              = "false"
  allow_global_access    = "false"
  ip_address             = var.vpn_static_ip
  ip_protocol            = "UDP"
  is_mirroring_collector = "false"
  load_balancing_scheme  = "EXTERNAL"
  name                   = "my-rule-udp500"
  network_tier           = "PREMIUM"
  port_range             = "500-500"
  target                 = google_compute_vpn_gateway.vpn_gateway.self_link
}

これで見事疎通しました🎉

接続できるとRTX830のダッシュボードでも確認できます。ここではさらにリモートアクセスVPNの設定もしてみております。

また、Google CloudのCompute Engine(192.168.200.11)から自宅のゲーミングPC(192.168.100.55)で動いてるLocalAIサーバへのリクエストも成功しました🎉

abekoh@bastion:~$ curl http://192.168.100.55:6502/v1/chat/completions -H "Content-Type: application/json" -d '{
  "model": "meta-llama-3.1-8b-instruct",
  "messages": [{"role": "user", "content": "Please tell me about IPSec VPN"}],
  "temperature": 0.7
}'
{"created":1729785168,"object":"chat.completion","id":"8c61bf2a-101f-495c-9a7d-7c71ed1fe474","model":"meta-llama-3.1-8b-instruct","choices":[{"index":0,"finish_reason":"stop","message":{"role":"assistant","content":"IPSec VPN (Internet Protocol Security Virtual Private Network) is a widely used technology for establishing secure, encrypted connections between two or more networks over the internet. Here's a rundown on how it works and its key components:\n\n**What is IPSec?**\n\nIPSec (Internet Protocol Security) is a suite of protocols designed to provide security and privacy to IP communications. It was developed by the Internet Engineering Task Force (IETF) and is now a standard part of the IP protocol suite.\n\n**How does IPSec VPN work?**\n\nAn IPSec VPN creates a secure \"tunnel\" between two endpoints, typically between a remote user's device and a corporate network or between two sites. Here's a simplified overview of the process:\n\n1. **Key exchange**: The two endpoints agree on a shared secret key, which is used to encrypt and decrypt data.\n2. **IPSec tunnel**: The endpoints establish an IPSec tunnel, which is a secure connection between them.\n3. **Encapsulation**: Data is encapsulated in IPSec packets, which are then encrypted using the shared secret key.\n4. **Transmission**: The encrypted packets are transmitted over the internet.\n5. **Decapsulation**: The receiving endpoint decrypts the packets, which are then reassembled into the original data.\n\n**Key components of IPSec VPN**\n\n1. **Authentication Header (AH)**: Provides authentication and integrity of the data.\n2. **Encapsulating Security Payload (ESP)**: Provides encryption and confidentiality of the data.\n3. **Internet Key Exchange (IKE)**: Manages the key exchange process between endpoints.\n4. **Security Associations (SAs)**: Define the security parameters for the IPSec tunnel, including the shared secret key and encryption algorithms.\n\n**Benefits of IPSec VPN**\n\n1. **Security**: IPSec VPN provides end-to-end encryption and authentication, protecting data from eavesdropping and tampering.\n2. **Confidentiality**: IPSec VPN ensures that data remains confidential, even if it's intercepted during transmission.\n3. **Integrity**: IPSec VPN ensures that data is not modified or tampered with during transmission.\n4. **Scalability**: IPSec VPN can be used to connect multiple sites or remote users, making it a scalable solution.\n\n**Common deployment scenarios for IPSec VPN**\n\n1. **Remote access VPN**: Connects remote users to a corporate network or site.\n2. **Site-to-site VPN**: Connects two or more sites over the internet.\n3. **Extranet VPN**: Connects a company's network to a partner's network or a service provider's network.\n\nI hope this helps you understand IPSec VPN!"}}],"usage":{"prompt_tokens":17,"completion_tokens":541,"total_tokens":558}}

おわりに

疎通できたはよいものの、VPC繋ぎっぱなしだとトラフィックがなくとも1時間0.05ドル、1日1.2ドル、1ヶ月36ドル=5000円超かかってしまいます。(us-west1の場合)

個人で払うにはちと高いですね。なので利用時のみ繋げられるよう、terraform apply, terraform destroyするCloud Runジョブも用意してみました。これを呼び出す自分用UIも作成しようと模索中…

setup-job

構築したはいいものの、肝心のローカルLLMで何しようかなってところは決まっていない模様。ともかくネットワーク、VPNに関して知見が深まったので良しとします。