July 18, 2024

Wireguard 서버 설정과 iptime 공유기를 이용한 연결 과정

Wireguard 서버 설정과 iptime 공유기를 이용한 연결 과정
Photo by Privecstasy / Unsplash

목적

이전에 iptime의 Wireguard Server 기능을 이용해 통신을 시도했다가 iptime의 라우팅 등의 기능으로는 Azure VM과의 통신이 불가하였다.

https://dogring.wordpress.com/2024/07/07/iptime-%EA%B3%B5%EC%9C%A0%EA%B8%B0-wireguard-%EC%84%9C%EB%B2%84-%EC%84%A4%EC%A0%95%EA%B3%BC-azure-vm-%EC%97%B0%EA%B2%B0-%EB%8B%A8%EA%B3%84%EB%B3%84-%EC%95%88%EB%82%B4/

해당 과정을 iptime 공유기의 Wireguard Client 기능을 이용해서 통신을 구성해 본다.

VM 설정

Variables :

  • SERVER/Client PRIVATE/PUBLIC KEY : wg 연결 키
  • SERVER_IP : VPN 을 구성하는 VM의 public ip
  • SERVER_PORT : VPN에 사용할 vpn port (임의 설정)
  • SERVER_WG_INTERFACE : Wireguard 인터페이스 이름 (보통 wg0)
  • SERVER_VPN_IP, CLIENT_VPN_IP : Wireguard 의 인터페이스 ip
  • WG_DIR : wireguard config 위치
#!/bin/bash

# Install WireGuard
sudo apt update && sudo apt upgrade -y
sudo apt install -y wireguard

# Update /etc/hosts to resolve host name issue
sudo sh -c 'echo "127.0.1.1 $(hostname)" >> /etc/hosts'

# Variables
SERVER_PRIVATE_KEY=$(wg genkey)
SERVER_PUBLIC_KEY=$(echo $SERVER_PRIVATE_KEY | wg pubkey)
CLIENT_PRIVATE_KEY=$(wg genkey)
CLIENT_PUBLIC_KEY=$(echo $CLIENT_PRIVATE_KEY | wg pubkey)
SERVER_IP=${server_ip}
SERVER_PORT=${vpn_port}
SERVER_WG_INTERFACE="wg0"
SERVER_VPN_IP="10.10.255.128/25"
CLIENT_VPN_IP="10.10.255.129/25"
CLIENT_NETWORK="192.168.0.0/24"
WG_DIR="/etc/wireguard"
SERVER_WG_CONFIG="$WG_DIR/$SERVER_WG_INTERFACE.conf"
CLIENT_WG_CONFIG="$WG_DIR/client.conf"

# Server config
echo "[Interface]
PrivateKey = $SERVER_PRIVATE_KEY
Address = $SERVER_VPN_IP
ListenPort = $SERVER_PORT

[Peer]
PublicKey = $CLIENT_PUBLIC_KEY
AllowedIPs = $CLIENT_VPN_IP, $CLIENT_NETWORK
" | sudo tee $SERVER_WG_CONFIG

# client config
echo "[Interface]
PrivateKey = $CLIENT_PRIVATE_KEY
Address = $CLIENT_VPN_IP
DNS = 8.8.8.8

[Peer]
PublicKey = $SERVER_PUBLIC_KEY
Endpoint = $SERVER_IP:$SERVER_PORT 
AllowedIPs = 10.0.0.0/8
" | sudo tee $CLIENT_WG_CONFIG

# Start WireGuard
sudo wg-quick up $SERVER_WG_INTERFACE
sudo systemctl enable wg-quick@$SERVER_WG_INTERFACE

# Set IP Forwarding
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
sudo ip route add $SERVER_VPN_IP dev wg0

# save iptables
sudo debconf-set-selections <<EOF
iptables-persistent iptables-persistent/autosave_v4 boolean true
iptables-persistent iptables-persistent/autosave_v6 boolean true
EOF
sudo apt-get -y install iptables-persistent

AllowedIPs 를 추가하게 되면 ip route 등 네트워크 설정이 자동으로 구성됩니다.

그 후 /etc/wireguard/client.conf 의 값을 가져옵니다.

iptime 설정

iptime WireGuard Client 구성

/etc/wireguard/client.conf의 값을 이용하여 구성합니다.
VPN 서버에 접속하지 않고 진행하기 위해선 wg 연결 키를 외부에서 생성하여 집어 넣습니다.

iptime VPN 클라이언트 사용 관리

통신하고 싶은 단말과, 목적지 IP를 설정합니다.
(192.168.0.0/24 -> 10.0.0.0/8 트래픽을 VPN으로 전송)

Terraform 을 이용한 network 구성

NIC ip forwarding

resource "azurerm_network_interface" "main" {
  ...
  enable_ip_forwarding = true
  ...
}

NSG 구성

VPN 포트 하나만 구성

resource "azurerm_network_security_group" "main" {
  name = "vpn-nsg"
  location = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name

  security_rule {
    name = "WireGuard-Inbound"
    priority = 100
    direction = "Inbound"
    access = "Allow"
    protocol = "Udp"
    source_port_range = "*"
    destination_port_ranges = [var.vpn_port]
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }
}
resource "azurerm_subnet_network_security_group_association" "main" {
  subnet_id                 = azurerm_subnet.main.id
  network_security_group_id = azurerm_network_security_group.main.id
}

Route Table 구성

route table이 없을 경우 통신이 되지 않습니다.


resource "azurerm_route_table" "main" {
  name = "vpn-rt"
  location = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
}

# VPN VM 으로 192.168.0.0/24 트래픽 전송
resource "azurerm_route" "vpn" {
  name = "vpn-route-vpn"
  resource_group_name = azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "192.168.0.0/24"
  next_hop_type = "VirtualAppliance"
  next_hop_in_ip_address = azurerm_network_interface.main.private_ip_address
}

# VPN VM 으로 VPN Interface IP 트래픽 전송
resource "azurerm_route" "vpn-client" {
  name = "vpn-route-vpn-client"
  resource_group_name = azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "10.10.255.128/25"
  next_hop_type = "VirtualAppliance"
  next_hop_in_ip_address = azurerm_network_interface.main.private_ip_address
}

resource "azurerm_route" "IGW" {
  name = "vpn-route-igw"
  resource_group_name = azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "0.0.0.0/0"
  next_hop_type = "Internet"
}

resource "azurerm_subnet_route_table_association" "main" {
  subnet_id = azurerm_subnet.main.id
  route_table_id = azurerm_route_table.main.id
}

외부 Azure VM 의 Network 구성

Subnet peering 설정

resource "azurerm_virtual_network_peering" "VPN-to-Node" {
  name = "vpn-to-node"
  resource_group_name = data.azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.main.name
  remote_virtual_network_id = data.azurerm_virtual_network.vpn.id
  allow_virtual_network_access = true
}

resource "azurerm_virtual_network_peering" "Node-to-VPN" {
  name = "node-to-vpn"
  resource_group_name = data.azurerm_resource_group.main.name
  virtual_network_name = data.azurerm_virtual_network.vpn.name
  remote_virtual_network_id = azurerm_virtual_network.main.id
  allow_virtual_network_access = true
}

Route Table 설정

resource "azurerm_route_table" "main" {
  name = "Nodert"
  location = data.azurerm_resource_group.main.location
  resource_group_name = data.azurerm_resource_group.main.name
}

# 192.168.0.0/24, 10.10.255.128/25 의 트래픽 전송
resource "azurerm_route" "Node" {
  name = "Noderoute-vpn"
  resource_group_name = data.azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "192.168.0.0/24"
  next_hop_type = "VirtualAppliance"
  next_hop_in_ip_address = data.azurerm_network_interface.vpn.private_ip_address
}

resource "azurerm_route" "vpn-client" {
  name = "vpn_client"
  resource_group_name = data.azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "10.10.255.128/25"
  next_hop_type = "VirtualAppliance"
  next_hop_in_ip_address = data.azurerm_network_interface.vpn.private_ip_address
}

resource "azurerm_route" "main" {
  name = "Noderoute-igw"
  resource_group_name = data.azurerm_resource_group.main.name
  route_table_name = azurerm_route_table.main.name
  address_prefix = "0.0.0.0/0"
  next_hop_type = "Internet"
}

resource "azurerm_subnet_route_table_association" "main" {
  subnet_id = azurerm_subnet.main.id
  route_table_id = azurerm_route_table.main.id
}

Comments