はじめに
我が家には数年前に組んだ「GeForce RTX 3080搭載のゲーミングPC」があるわけですが、最近はPCゲームをそこまでやらず、それなりのGPUあるのにもったいないなという状態です。
最近はローカルLLMの性能も良くなり、せっかくなのでそれなりのGPU積んだゲーミングPCをAIマシンにして有効活用できないかな、と思い。それなら自宅以外、クラウドからも呼び出せると嬉しいだろうなーと妄想してました。
そのはじめの一歩として、IPSec VPNで自宅ネットワークとGoogle Cloud VPCを繋ぐ仕組みを整えてみました。そのログです。
Overview
全体イメージはこちら。Google Cloudのほうはとりあえず疎通確認のためにCompute Engineのみ。自宅のほうはYAMAHAルータを中心にネットワークを構築してみてます。
自宅ネットワークの刷新
自宅の回線はNuro光で、今までZTE F660Aという端末にONU、ルータ、Wi-Fiアクセスポイントすべての役割を任せていました。 Google Cloudとの拠点間VPNをセットアップするためにはIPSecを用いたVPNに対応したルータが必要で、F660Aはそれには対応しておりません。というか家庭向けルータはIPSec VPNに対応しているほうが珍しいです。
そこで界隈では名高い業務用ルータ、YAMAHA製のルータに手を出してみることにしました。なんとなく憧れがあったので良い機会です。
入手したのはこちらRTX830。希望小売価格なんと101,200円(税込)! …この値段だと流石にな、とは思いましたが、メルカリで探すと中古2万円程度の出品がたくさんあったので購入。業務用の安定高機能なルータが2万はお買い得な気がします。
ルータが到着して、いざ設定開始。F660AはONU機能のみに限定、ルーティングはすべてRTX830のほうで行ってもらうようにしました。 このあたりの設定は先人のログがたくさん見つかったので参考にさせていただきました。
- Nuro光 + RTX1200 で VPNが使えるようにする(一部制限あり)- 逸般の誤家庭 向け情報 - ものくろぼっくす
- Nuro光のONUに自前ルータを接続する - TALKEYBOID Blog
- NURO光でF660Aへの接続台数が10台を超えると不安定になる事象を解決する - うっかりエンジニアのメモ
やったことまとめるとざっくり↓
- 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を購入、ブリッジモードでセットしました。
以上が自宅ネットワークの刷新です。
YAMAHAルータ導入した。これで我が家も逸般の誤家庭 pic.twitter.com/aOJvIiMMNN
— abekoh (@abekoh_my) October 2, 2024
ついでに、ネットワーク途切れる問題も解決したっぽい。
YouTube Liveが切れまくる問題がなくなって快適
— abekoh (@abekoh_my) October 6, 2024
YAMAHAルータだから、というよりONUとルータを分離させたからな気はするけど
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」を採用します。
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の設定もしてみております。
リモートアクセスVPN、Google Cloudとの拠点間VPNも設定いけた pic.twitter.com/sBGIdviXVW
— abekoh (@abekoh_bcky) October 6, 2024
また、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も作成しようと模索中…
構築したはいいものの、肝心のローカルLLMで何しようかなってところは決まっていない模様。ともかくネットワーク、VPNに関して知見が深まったので良しとします。