Nebula Overlay Networking
A scalable overlay networking tool with a focus on performance, simplicity and security
Nebula is an overlay networking tool designed to be fast, secure, and scalable. Connect any number of hosts with on-demand, encrypted tunnels that work across any IP networks and without opening firewall ports.
Features
- 멀티 클라우드/로케이션에 퍼져있는 수많은 노드를 연결해주는 도구.
- 간결하면서도 성능과 보안에 중점을 두고 개발.
- 슬랙이 초기엔 IPSec을 이용하다 자체개발해서 2년째 사용중.
- Noise Protocol Framework 에 기반한 상호 인증된 P2P 소프트웨어 정의 네트워크.
클라우드 서비스들이 자체적인 시큐리티그룹들을 지원하지만, 각 서비스와 지역에만 종속적이고, 여러 서비스들간에 연결이 가능하지 않음. 이를 해결하기 위해 암호화,시큐리티그룹,인증서,터널링 등을 한데 병합한 솔루션.
- 호스트간 암호화된 연결 지원
- 서비스 비 종속 - 클라우드/데이터센터/개인노트북 이든 상관없음
- 고수준 트래픽 필터링
- 강력한 아이덴티티 제공
- 최대한 빠르게
- 네트웍 변경에 대한 테스트 가능
Components of a Nebula network
등대 (Lighthouse)
Nebula에서 Lighthouse(등대)는 다른 모든 Nebula 호스트를 추적하고 Nebula 네트워크 내에서 서로를 찾을 수 있도록 돕는 Nebula 호스트입니다.
오버레이 네트워크에서 최소한 하나의 호스트는 호스트가 Lighthouse(등대)여야 합니다. Lighthouse 는 서로에 대한 경로를 검색하고 NAT 통과를 지원합니다.
인증 기관 (Certificate Authority; CA)
가장 간단한 형태의 Nebula 인증 기관(CA)은 두 개의 파일, 즉 CA 인증서와 관련 개인 키로 구성됩니다.
CA 인증서는 네트워크의 모든 호스트에 배포되고 신뢰됩니다.
CA 개인 키는 배포되어서는 안 되며, Nebula 네트워크에 호스트를 추가하는 데 사용되지 않을 때는 오프라인으로 유지될 수 있습니다.
호스트 (Hosts)
Nebula 호스트는 단순히 네트워크의 단일 노드(예: 서버, 노트북, 휴대폰, 태블릿)입니다.
인증 기관은 Nebula 네트워크에 추가된 각 호스트에 대한 키에 서명하는 데 사용됩니다.
호스트 인증서 (Host Certificate) 에는 이름, IP 주소, 그룹 멤버십 및 호스트에 대한 기타 여러 세부 정보가 포함되어 있습니다.
개별 호스트는 자신의 인증서를 수정할 수 없습니다. 수정하면 인증서가 무효화되기 때문입니다. 이를 통해 우리는 호스트가 Nebula 네트워크 내에서 다른 호스트를 가장할 수 없다는 것을 신뢰할 수 있습니다. 각 호스트에는 Nebula 터널이 생성될 때 해당 호스트의 신원을 확인하는 데 사용되는 자체 개인 키가 있습니다.
다운로드 및 설치
sudo -s
curl -L https://github.com/slackhq/nebula/releases/download/v1.9.1/nebula-linux-amd64.tar.gz | tar xzf - -C /usr/bin
첫 번째 인증 기관 만들기
Nebula는 v1.7.0부터 CA 개인 키의 내장 암호화를 제공합니다. 암호화된 스토리지(예:
Ansible Vault
또는
AWS Secrets Manager
)에 프라이빗 키를 저장할 계획이 없다면 내장된 암호화를 사용하는 것이 좋습니다.
Nebula 개인 키를 암호화하려면 CA를 생성할 때 ``-encrypt`` 플래그를 전달하면 암호를 입력하라는 메시지가 표시됩니다. 안전하게 보관하세요. 암호화된 CA 키를 사용하여 호스트에 서명할 때마다 이를 묻는 메시지가 표시됩니다.
Nebula는 키 파생을 위해
Argon2id와
함께
AES-256-GCM
암호화를 사용합니다.
기본
Argon2
매개변수는 Argon2 RFC (1회 반복, 4레인 병렬 처리, 2GiB RAM)의 "FIRST RECOMMENDED" 제안에서 가져옵니다.
고유한 매개변수를 선택하려면 ``-argon-iterations``, ``-argon-parallelism``및 ``-argon-memory`` CLI 플래그를 사용합니다.
Nebula는 인증 기관을 사용하여 Nebula 네트워크 내의 개별 호스트를 식별합니다. 자신만의 Nebula 네트워크를 만드는 첫 번째 단계는 조직에 대한 인증 기관을 만드는 것입니다. Nebula 네트워크에 새 호스트를 추가하면 조직에서 호스트를 신뢰할 수 있음을 증명하는 자격 증명을 생성하는 데 인증 기관이 사용됩니다.
그러면 현재 디렉터리에 ca.key
및 ca.cert
라는 이름의 파일이 생성됩니다.
ca.key
파일은 개별 Nebula 호스트에 대한 인증서에 서명하는 데 사용되는 키이기 때문에 생성할 가장 민감한 파일입니다. 이 파일을 안전한 곳에 저장하세요. 가급적이면 강력한 암호화를 사용하세요.
INFORMATION |
기본적으로 이 CA는 1년 만료로 생성되며 서명된 모든 인증서는 CA가 만료되기 1초 전까지 유효합니다. 지속적인 연결을 보장하려면 그 전에 CA 및 인증서를 교체 하도록 경고 또는 달력 이벤트를 설정하십시오! |
CA 가 유효한 사용자 지정 기간을 설정하려면 -duration XXhXXmXXs
플래그를 전달하면 됩니다. 예를 들어 -duration 17531h
를 사용하면 2년 미만 동안 유효한 CA를 생성합니다.
Building a Nebula network
등대 설립 (Establishing a Lighthouse)
Nebula의 Lighthouse는 호스트가 세계 어디에서나 서로를 찾을 수 있게 해줍니다. Lighthouse는 IP 주소가 변경되어서는 안 되는 Nebula 네트워크의 유일한 호스트입니다.
등대를 운영하려면 컴퓨팅 리소스가 거의 필요하지 않으며 클라우드 호스팅 공급자가 제공하는 가장 저렴한 옵션을 쉽게 사용할 수 있습니다.
어떤 공급자를 사용해야 할지 확실하지 않은 경우, 우리 중 다수는 월 $5의 DigitalOcean droplets 을 등대로 사용했습니다.
인스턴스를 시작한 후에는 Nebula UDP 트래픽(기본 포트 udp/4242)이 인터넷을 통해 인스턴스에 도달할 수 있고 인바운드 방화벽에 의해 차단되지 않는지 확인하세요.
iptables를 사용한다면:
Creating Keys and Certificates
여기서는 lighthouse1, laptop, server라는 세 개의 호스트가 있다고 가정합니다.
FQDN을 포함하여 원하는 방식으로 호스트 이름을 지정할 수 있습니다.
또한 인증서를 생성할 때 각 호스트에 대한 Nebula IP 주소를 선택해야 합니다. 이 예에서는 서브넷을 사용하는 Nebula 네트워크를 만들고 192.168.100.x/24
이 서브넷 내의 각 호스트에 IP 주소를 할당합니다.
이 예에서는 나중에 Nebula Network 에서 Traffic Rules을 정의하는 데 사용할 수 있는 Nebula Group을 보여줍니다.
./nebula-cert sign -name "lighthouse1" -ip "192.168.100.1/24"
./nebula-cert sign -name "laptop" -ip "192.168.100.5/24" -groups "laptop,ssh"
./nebula-cert sign -name "server" -ip "192.168.100.9/24" -groups "servers"
Configuring Nebula
INFORMATION |
다음 예에서는 주소 |
Nebula 의 Example Config 를 다운로드 받고, Lighthouse 용 config-lighthouse.yaml
와 그 외의 모든 호스트용 config.yaml
파일로 복사하세요:
curl -o config.yml https://raw.githubusercontent.com/slackhq/nebula/master/examples/config.yml
cp config.yml config-lighthouse.yaml
cp config.yml config.yaml
파일을 새로 만들지 말고 예제를 복사한 후 아래에 설명된 부분만 수정하자.
Lighthouse configuration (config-lighthouse.yaml)
Lighthouse 는 am_lighthouse: true
가 있는지 확인하면 된다.
일반적으로 등대에는 static_host_map
에 항목이 없습니다. 모든 호스트가 자신을 등대에 보고하기 때문입니다. 여러 개의 등대를 사용하는 경우 일반적으로 서로에 대해 알 필요가 없습니다.
Host configuration (config.yaml)
개별 호스트들은 Lighthouse 가 static_host_map
섹션에 올바르게 정의되어 있고, lighthouse > hosts
가 추가되었는지 확인하세요.
static_host_map:
'192.168.100.1': ['198.51.100.1:4242']
lighthouse:
am_lighthouse: false
interval: 60
# `hosts`는 이 노드가 보고하고 쿼리해야 하는 Lighthouse 호스트 목록입니다.
# 중요 1: Lighthouse 노드에서는 비어 있어야 합니다.
# 중요 2: 이는 LIGHTHOUSES의 실제 라우팅 가능한 IP가 아니라 LIGHTHOUSES의 Nebula IP 여야 합니다.
hosts:
- '192.168.100.1'
방화벽 구성
예제 구성 파일은 모든 아웃바운드 트래픽을 허용하지만 각 Nebula 호스트에 대한 특정 연결만 허용합니다. 네트워크 내 호스트와의 트래픽을 허용하려면 이러한 설정을 수정해야 합니다.
firewall:
outbound:
# Allow all outbound traffic from this node
- port: any
proto: any
host: any
inbound:
# Allow icmp between any nebula hosts
- port: any
proto: icmp
host: any
만약 Nebula Network 로 트래픽이 전송되고 iptable을 사용한다면 양 쪽 모두 방화벽 설정을 해야한다.... 개 귀찮게스리..
기본 설정으로 아무런 셋팅이 없으면 In/Out 바운드는 DROP 이다:
만약 6443/tcp 포트를 열고 싶다면:
그리고 필요하다면: iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 6443 -j ACCEPT
Running Nebula
구성, 인증서 및 키 파일이 생성되면 마지막 단계는 적절한 파일을 각 호스트에 복사하고 Nebula 네트워크를 시작하는 것입니다.
Lighthouse
- Lighthouse 에 다음 파일을 복사하세요:
nebula
바이너리,config-lighthouse.yaml
,ca.crt
,lighthouse1.crt
, andlighthouse1.key
절대로ca.key
파일은 복사하면 안됩니다!!! - SSH to your lighthouse.
- Create a directory named
/etc/nebula
on your lighthouse host. - 구성, 인증서, 키 파일들을 적절한 디렉터리로 이동합니다.
mv config-lighthouse.yaml /etc/nebula/config.yaml mv ca.crt /etc/nebula/ca.crt mv lighthouse.crt /etc/nebula/host.crt mv lighthouse.key /etc/nebula/host.key
</syntaxhighlight>
- Start Nebula:
./nebula -config /etc/nebula/config.yaml
Hosts
이 예에서는 위에서 생성한 server라는 호스트를 구성합니다. 적절한 파일 이름으로 대체하십시오.
- Host 에 다음 파일을 복사하세요:
nebula
바이너리,config.yaml
,ca.crt
,server.crt
, andserver.key
절대로ca.key
파일은 복사하면 안됩니다!!! - SSH to the host you've named server.
- Create a directory named
/etc/nebula
on the Nebula host. - Move the configuration, certificates, and key into the appropriate directory.
- 참고로 예제 구성에서는 호스트 인증서와 키의 이름이
host.crt
및host.key
라고 가정하므로 파일을 적절한 디렉터리로 이동할 때 일부 파일의 이름을 바꿔야 합니다.
- 참고로 예제 구성에서는 호스트 인증서와 키의 이름이
mv config.yaml /etc/nebula/config.yaml mv ca.crt /etc/nebula/ca.crt mv server.crt /etc/nebula/host.crt mv server.key /etc/nebula/host.key
</syntaxhighlight>
- Start Nebula:
./nebula -config /etc/nebula/config.yaml
파일들 권한 조정
cd /etc/nebula
sudo chmod 600 ca.crt config.yml host.crt host.key
sudo chown root:root ca.crt config.yml host.crt host.key
Verifying it all works
이제 Nebula를 실행하는 다른 호스트에 ping을 보낼 수 있습니다(ICMP가 허용된다고 가정). 예시의 lighthouse 를 PING 하려면 다음을 실행하세요.
Relay
INFORMATION |
결론만 말하면 통신하려는 양 측 호스트가 모두 Symmetric NAT 안에 감춰져 있다면 결국 이런 방법을 써야 한다. |
릴레이 호스트는 두 피어 간에 트래픽을 전달합니다. 이는 두 노드가 서로 직접 통신하는 데 어려움을 겪는 경우 유용할 수 있습니다(예: 일부 NAT에서는 두 노드 간의 직접 연결 설정이 어려울 수 있습니다.)
다른 호스트에 대한 릴레이 역할을 하려면 반드시 am_relay: true
(기본값은 false
)로 설정되어야 합니다.
릴레이를 사용하려면 해당 호스트가 use_relays: true
(기본값은 true
)로 설정되어 있어야 합니다.
모든 호스트가 릴레이가 될 수 있습니다. 꼭 등대(Lighthouse)일 필요는 없습니다. 그러나 등대와 마찬가지로 릴레이 노드는 Nebula의 UDP 트래픽 인바운드를 허용하는 공용 인터넷 IP 및 방화벽 규칙을 사용하여 배포되어야 합니다.
relays
에 열거된 Nebula IP 목록은 현재 호스트에 패킷을 중계하는 데 사용할 수 있는 릴레이 역할을 할 수 있는 다른 호스트 입니다. 즉, 이 목록의 IP는 구성에서 am_relay: true
로 설정 되어 있어야 합니다. 그렇지 않으면 릴레이 요청을 거부합니다.
이를 통해 호스트는 자신과 "가까운" 릴레이를 지정할 수 있습니다. 예를 들어, 프라이빗 AWS VPC에 일부 Nebula 호스트가 있는 경우 해당 VPC의 피어에 대한 연결을 활성화하는 전용 릴레이 호스트를 설정할 수 있습니다.
릴레이로 릴레이할 수 없습니다. 릴레이(am_relay: true
)로 구성된 호스트는 자체 구성에서 다른 호스트를 릴레이로 지정할 수 없습니다.
릴레이 설정 예시:
INFORMATION |
|
iptables
iptables 방화벽 설정했다면 Nebula 의 config.yml 안에 listen.port
값을 0 을 사용하지 말아라. (문서상의 기본 값인 4242 을 사용한다는 가정으로 진행)
그리고 아래와 같이 설정:
## 통신 프로토콜
-A INPUT -p udp --sport 4242 -j ACCEPT
## VPN 인터페이스를 모두 ACCEPT -> 이 설정은 nebula 의 자체 firewall 설정으로 모두 대체하기 위함.
-A INPUT -i nebula1 -j ACCEPT
보안 관련 문제
- Strider: Network Pivoting with Nebula - 방어 시스템의 탐지를 피하기 위해 "Living off the Land"라는 개념을 사용합니다.
작동 원리
Nebula는 중앙 게이트웨이를 거치지 않고 노드가 서로 직접 통신하는 소위 메시 네트워크 입니다. 이는 네트워킹 속성을 영리하게 활용하여 작동합니다.
하루에 수천 번 발생하는 일반적인 네트워킹 흐름은 다음과 같습니다 (터무니없이 단순화됨).
How_Nebula_works_-_flow.png
연결을 설정할 때 클라이언트는 서버의 응답을 위해 포트를 엽니다. 클라이언트와 서버 사이의 방화벽과 라우터는 이 프로세스를 알고 클라이언트로 돌아가는 트래픽이 허용되는지 확인합니다.
Nebula는 이 개방형 포트를 사용하여 방화벽을 교묘하게 통과하고 클라이언트를 서로 직접 연결합니다. 성운 용어로 Lighthouse 라고 불리는 특수 노드 는 클라이언트가 서로를 발견하도록 하는 데 사용됩니다. 이 특수 노드는 공개적으로 연결 가능한 IP 주소를 가져야 하는 유일한 네트워크 구성원입니다. 클라이언트는 먼저 Lighthouse에 연결하고 로컬 포트를 엽니다. 그러나 Lighthouse는 직접 응답하지 않고 대상 클라이언트에게 새로 열린 포트에 응답하도록 지시합니다. 이 과정은 반대쪽에서도 반복됩니다.
How_Nebula_works_-_discovery.png
이는 매우 단순화된 다이어그램입니다. 실제로는 원활한 NAT 통과를 위해 훨씬 더 많은 스푸핑과 속임수가 진행되고 있습니다.
Authentication
WireGuard에 비해 큰 장점 중 하나는 Nebula가 인증을 처리하는 방식입니다. WireGuard는 관리자가 새 클라이언트의 공개 키를 기존 노드의 구성에 통합할 것으로 기대합니다. 이론적으로는 간단하지만 이 접근 방식은 확장성이 뛰어나지 않으며 새 노드를 자동으로 출시하려면 추가 도구가 필요합니다. Tailscale 과 동료는 이러한 복잡성을 관리하는 좋은 방법이지만 추가 서비스와 추상화를 도입하는 대가를 치르게 됩니다.
Nebula는 공개 키 인프라 (PKI) 개념을 활용하여 이 문제를 해결합니다. 중앙 인증 기관 (CA)은 클라이언트의 인증서에 서명합니다. 이러한 인증서는 관리 목적뿐만 아니라 암호화 목적으로도 사용됩니다. 서명에는 노드의 IP 주소뿐만 아니라 허용된 서브넷 및 그룹과 같은 기타 메타데이터도 포함됩니다.
새로운 클라이언트가 Lighthouse에 등록할 때마다 인증 기관에 인증서를 확인하고 인증서에 저장된 IP 주소를 기억합니다. CA 자체는 변경되지 않으므로 Lighthouse는 구성된 후 생성된 클라이언트를 확인할 수 있으며 이러한 변경 사항에 적응할 필요가 없습니다.
내가 적용한 설정
Blackhole#Nebula 항목 참조.
Nebula vs Tailscale
systemd 서비스로 기동하기
/etc/systemd/system/nebula.service
에 파일 저장:
[Unit]
Description=Nebula VPN
After=network.target
[Service]
ExecStart=/path/to/nebula -config /path/to/config.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target
서비스 파일 로드/부팅 시작 등록/실행:
config.yml examples
공식 샘플을 원본으로 수정하자.
다운받은 원본은 다음과 같다:
# This is the nebula example configuration file. You must edit, at a minimum, the static_host_map, lighthouse, and firewall sections
# Some options in this file are HUPable, including the pki section. (A HUP will reload credentials from disk without affecting existing tunnels)
# PKI defines the location of credentials for this node. Each of these can also be inlined by using the yaml ": |" syntax.
pki:
# The CAs that are accepted by this node. Must contain one or more certificates created by 'nebula-cert ca'
ca: /etc/nebula/ca.crt
cert: /etc/nebula/host.crt
key: /etc/nebula/host.key
# blocklist is a list of certificate fingerprints that we will refuse to talk to
#blocklist:
# - c99d4e650533b92061b09918e838a5a0a6aaee21eed1d12fd937682865936c72
# disconnect_invalid is a toggle to force a client to be disconnected if the certificate is expired or invalid.
#disconnect_invalid: true
# The static host map defines a set of hosts with fixed IP addresses on the internet (or any network).
# A host can have multiple fixed IP addresses defined here, and nebula will try each when establishing a tunnel.
# The syntax is:
# "{nebula ip}": ["{routable ip/dns name}:{routable port}"]
# Example, if your lighthouse has the nebula IP of 192.168.100.1 and has the real ip address of 100.64.22.11 and runs on port 4242:
static_host_map:
"192.168.100.1": ["100.64.22.11:4242"]
# The static_map config stanza can be used to configure how the static_host_map behaves.
#static_map:
# cadence determines how frequently DNS is re-queried for updated IP addresses when a static_host_map entry contains
# a DNS name.
#cadence: 30s
# network determines the type of IP addresses to ask the DNS server for. The default is "ip4" because nodes typically
# do not know their public IPv4 address. Connecting to the Lighthouse via IPv4 allows the Lighthouse to detect the
# public address. Other valid options are "ip6" and "ip" (returns both.)
#network: ip4
# lookup_timeout is the DNS query timeout.
#lookup_timeout: 250ms
lighthouse:
# am_lighthouse is used to enable lighthouse functionality for a node. This should ONLY be true on nodes
# you have configured to be lighthouses in your network
am_lighthouse: false
# serve_dns optionally starts a dns listener that responds to various queries and can even be
# delegated to for resolution
#serve_dns: false
#dns:
# The DNS host defines the IP to bind the dns listener to. This also allows binding to the nebula node IP.
#host: 0.0.0.0
#port: 53
# interval is the number of seconds between updates from this node to a lighthouse.
# during updates, a node sends information about its current IP addresses to each node.
interval: 60
# hosts is a list of lighthouse hosts this node should report to and query from
# IMPORTANT: THIS SHOULD BE EMPTY ON LIGHTHOUSE NODES
# IMPORTANT2: THIS SHOULD BE LIGHTHOUSES' NEBULA IPs, NOT LIGHTHOUSES' REAL ROUTABLE IPs
hosts:
- "192.168.100.1"
# remote_allow_list allows you to control ip ranges that this node will
# consider when handshaking to another node. By default, any remote IPs are
# allowed. You can provide CIDRs here with `true` to allow and `false` to
# deny. The most specific CIDR rule applies to each remote. If all rules are
# "allow", the default will be "deny", and vice-versa. If both "allow" and
# "deny" IPv4 rules are present, then you MUST set a rule for "0.0.0.0/0" as
# the default. Similarly if both "allow" and "deny" IPv6 rules are present,
# then you MUST set a rule for "::/0" as the default.
#remote_allow_list:
# Example to block IPs from this subnet from being used for remote IPs.
#"172.16.0.0/12": false
# A more complicated example, allow public IPs but only private IPs from a specific subnet
#"0.0.0.0/0": true
#"10.0.0.0/8": false
#"10.42.42.0/24": true
# EXPERIMENTAL: This option may change or disappear in the future.
# Optionally allows the definition of remote_allow_list blocks
# specific to an inside VPN IP CIDR.
#remote_allow_ranges:
# This rule would only allow only private IPs for this VPN range
#"10.42.42.0/24":
#"192.168.0.0/16": true
# local_allow_list allows you to filter which local IP addresses we advertise
# to the lighthouses. This uses the same logic as `remote_allow_list`, but
# additionally, you can specify an `interfaces` map of regular expressions
# to match against interface names. The regexp must match the entire name.
# All interface rules must be either true or false (and the default will be
# the inverse). CIDR rules are matched after interface name rules.
# Default is all local IP addresses.
#local_allow_list:
# Example to block tun0 and all docker interfaces.
#interfaces:
#tun0: false
#'docker.*': false
# Example to only advertise this subnet to the lighthouse.
#"10.0.0.0/8": true
# advertise_addrs are routable addresses that will be included along with discovered addresses to report to the
# lighthouse, the format is "ip:port". `port` can be `0`, in which case the actual listening port will be used in its
# place, useful if `listen.port` is set to 0.
# This option is mainly useful when there are static ip addresses the host can be reached at that nebula can not
# typically discover on its own. Examples being port forwarding or multiple paths to the internet.
#advertise_addrs:
#- "1.1.1.1:4242"
#- "1.2.3.4:0" # port will be replaced with the real listening port
# EXPERIMENTAL: This option may change or disappear in the future.
# This setting allows us to "guess" what the remote might be for a host
# while we wait for the lighthouse response.
#calculated_remotes:
# For any Nebula IPs in 10.0.10.0/24, this will apply the mask and add
# the calculated IP as an initial remote (while we wait for the response
# from the lighthouse). Both CIDRs must have the same mask size.
# For example, Nebula IP 10.0.10.123 will have a calculated remote of
# 192.168.1.123
#10.0.10.0/24:
#- mask: 192.168.1.0/24
# port: 4242
# Port Nebula will be listening on. The default here is 4242. For a lighthouse node, the port should be defined,
# however using port 0 will dynamically assign a port and is recommended for roaming nodes.
listen:
# To listen on both any ipv4 and ipv6 use "::"
host: 0.0.0.0
port: 4242
# Sets the max number of packets to pull from the kernel for each syscall (under systems that support recvmmsg)
# default is 64, does not support reload
#batch: 64
# Configure socket buffers for the udp side (outside), leave unset to use the system defaults. Values will be doubled by the kernel
# Default is net.core.rmem_default and net.core.wmem_default (/proc/sys/net/core/rmem_default and /proc/sys/net/core/rmem_default)
# Maximum is limited by memory in the system, SO_RCVBUFFORCE and SO_SNDBUFFORCE is used to avoid having to raise the system wide
# max, net.core.rmem_max and net.core.wmem_max
#read_buffer: 10485760
#write_buffer: 10485760
# By default, Nebula replies to packets it has no tunnel for with a "recv_error" packet. This packet helps speed up reconnection
# in the case that Nebula on either side did not shut down cleanly. This response can be abused as a way to discover if Nebula is running
# on a host though. This option lets you configure if you want to send "recv_error" packets always, never, or only to private network remotes.
# valid values: always, never, private
# This setting is reloadable.
#send_recv_error: always
# Routines is the number of thread pairs to run that consume from the tun and UDP queues.
# Currently, this defaults to 1 which means we have 1 tun queue reader and 1
# UDP queue reader. Setting this above one will set IFF_MULTI_QUEUE on the tun
# device and SO_REUSEPORT on the UDP socket to allow multiple queues.
# This option is only supported on Linux.
#routines: 1
punchy:
# Continues to punch inbound/outbound at a regular interval to avoid expiration of firewall nat mappings
punch: true
# respond means that a node you are trying to reach will connect back out to you if your hole punching fails
# this is extremely useful if one node is behind a difficult nat, such as a symmetric NAT
# Default is false
#respond: true
# delays a punch response for misbehaving NATs, default is 1 second.
#delay: 1s
# set the delay before attempting punchy.respond. Default is 5 seconds. respond must be true to take effect.
#respond_delay: 5s
# Cipher allows you to choose between the available ciphers for your network. Options are chachapoly or aes
# IMPORTANT: this value must be identical on ALL NODES/LIGHTHOUSES. We do not/will not support use of different ciphers simultaneously!
#cipher: aes
# Preferred ranges is used to define a hint about the local network ranges, which speeds up discovering the fastest
# path to a network adjacent nebula node.
# This setting is reloadable.
#preferred_ranges: ["172.16.0.0/24"]
# sshd can expose informational and administrative functions via ssh. This can expose informational and administrative
# functions, and allows manual tweaking of various network settings when debugging or testing.
#sshd:
# Toggles the feature
#enabled: true
# Host and port to listen on, port 22 is not allowed for your safety
#listen: 127.0.0.1:2222
# A file containing the ssh host private key to use
# A decent way to generate one: ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" < /dev/null
#host_key: ./ssh_host_ed25519_key
# Authorized users and their public keys
#authorized_users:
#- user: steeeeve
# keys can be an array of strings or single string
#keys:
#- "ssh public key string"
# Trusted SSH CA public keys. These are the public keys of the CAs that are allowed to sign SSH keys for access.
#trusted_cas:
#- "ssh public key string"
# EXPERIMENTAL: relay support for networks that can't establish direct connections.
relay:
# Relays are a list of Nebula IP's that peers can use to relay packets to me.
# IPs in this list must have am_relay set to true in their configs, otherwise
# they will reject relay requests.
#relays:
#- 192.168.100.1
#- <other Nebula VPN IPs of hosts used as relays to access me>
# Set am_relay to true to permit other hosts to list my IP in their relays config. Default false.
am_relay: false
# Set use_relays to false to prevent this instance from attempting to establish connections through relays.
# default true
use_relays: true
# Configure the private interface. Note: addr is baked into the nebula certificate
tun:
# When tun is disabled, a lighthouse can be started without a local tun interface (and therefore without root)
disabled: false
# Name of the device. If not set, a default will be chosen by the OS.
# For macOS: if set, must be in the form `utun[0-9]+`.
# For NetBSD: Required to be set, must be in the form `tun[0-9]+`
dev: nebula1
# Toggles forwarding of local broadcast packets, the address of which depends on the ip/mask encoded in pki.cert
drop_local_broadcast: false
# Toggles forwarding of multicast packets
drop_multicast: false
# Sets the transmit queue length, if you notice lots of transmit drops on the tun it may help to raise this number. Default is 500
tx_queue: 500
# Default MTU for every packet, safe setting is (and the default) 1300 for internet based traffic
mtu: 1300
# Route based MTU overrides, you have known vpn ip paths that can support larger MTUs you can increase/decrease them here
routes:
#- mtu: 8800
# route: 10.0.0.0/16
# Unsafe routes allows you to route traffic over nebula to non-nebula nodes
# Unsafe routes should be avoided unless you have hosts/services that cannot run nebula
# NOTE: The nebula certificate of the "via" node *MUST* have the "route" defined as a subnet in its certificate
# `mtu`: will default to tun mtu if this option is not specified
# `metric`: will default to 0 if this option is not specified
# `install`: will default to true, controls whether this route is installed in the systems routing table.
# This setting is reloadable.
unsafe_routes:
#- route: 172.16.1.0/24
# via: 192.168.100.99
# mtu: 1300
# metric: 100
# install: true
# On linux only, set to true to manage unsafe routes directly on the system route table with gateway routes instead of
# in nebula configuration files. Default false, not reloadable.
#use_system_route_table: false
# TODO
# Configure logging level
logging:
# panic, fatal, error, warning, info, or debug. Default is info and is reloadable.
#NOTE: Debug mode can log remotely controlled/untrusted data which can quickly fill a disk in some
# scenarios. Debug logging is also CPU intensive and will decrease performance overall.
# Only enable debug logging while actively investigating an issue.
level: info
# json or text formats currently available. Default is text
format: text
# Disable timestamp logging. useful when output is redirected to logging system that already adds timestamps. Default is false
#disable_timestamp: true
# timestamp format is specified in Go time format, see:
# https://golang.org/pkg/time/#pkg-constants
# default when `format: json`: "2006-01-02T15:04:05Z07:00" (RFC3339)
# default when `format: text`:
# when TTY attached: seconds since beginning of execution
# otherwise: "2006-01-02T15:04:05Z07:00" (RFC3339)
# As an example, to log as RFC3339 with millisecond precision, set to:
#timestamp_format: "2006-01-02T15:04:05.000Z07:00"
#stats:
#type: graphite
#prefix: nebula
#protocol: tcp
#host: 127.0.0.1:9999
#interval: 10s
#type: prometheus
#listen: 127.0.0.1:8080
#path: /metrics
#namespace: prometheusns
#subsystem: nebula
#interval: 10s
# enables counter metrics for meta packets
# e.g.: `messages.tx.handshake`
# NOTE: `message.{tx,rx}.recv_error` is always emitted
#message_metrics: false
# enables detailed counter metrics for lighthouse packets
# e.g.: `lighthouse.rx.HostQuery`
#lighthouse_metrics: false
# Handshake Manager Settings
#handshakes:
# Handshakes are sent to all known addresses at each interval with a linear backoff,
# Wait try_interval after the 1st attempt, 2 * try_interval after the 2nd, etc, until the handshake is older than timeout
# A 100ms interval with the default 10 retries will give a handshake 5.5 seconds to resolve before timing out
#try_interval: 100ms
#retries: 20
# query_buffer is the size of the buffer channel for querying lighthouses
#query_buffer: 64
# trigger_buffer is the size of the buffer channel for quickly sending handshakes
# after receiving the response for lighthouse queries
#trigger_buffer: 64
# Nebula security group configuration
firewall:
# Action to take when a packet is not allowed by the firewall rules.
# Can be one of:
# `drop` (default): silently drop the packet.
# `reject`: send a reject reply.
# - For TCP, this will be a RST "Connection Reset" packet.
# - For other protocols, this will be an ICMP port unreachable packet.
outbound_action: drop
inbound_action: drop
# Controls the default value for local_cidr. Default is true, will be deprecated after v1.9 and defaulted to false.
# This setting only affects nebula hosts with subnets encoded in their certificate. A nebula host acting as an
# unsafe router with `default_local_cidr_any: true` will expose their unsafe routes to every inbound rule regardless
# of the actual destination for the packet. Setting this to false requires each inbound rule to contain a `local_cidr`
# if the intention is to allow traffic to flow to an unsafe route.
#default_local_cidr_any: false
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
# The firewall is default deny. There is no way to write a deny rule.
# Rules are comprised of a protocol, port, and one or more of host, group, or CIDR
# Logical evaluation is roughly: port AND proto AND (ca_sha OR ca_name) AND (host OR group OR groups OR cidr) AND (local cidr)
# - port: Takes `0` or `any` as any, a single number `80`, a range `200-901`, or `fragment` to match second and further fragments of fragmented packets (since there is no port available).
# code: same as port but makes more sense when talking about ICMP, TODO: this is not currently implemented in a way that works, use `any`
# proto: `any`, `tcp`, `udp`, or `icmp`
# host: `any` or a literal hostname, ie `test-host`
# group: `any` or a literal group name, ie `default-group`
# groups: Same as group but accepts a list of values. Multiple values are AND'd together and a certificate would have to contain all groups to pass
# cidr: a remote CIDR, `0.0.0.0/0` is any.
# local_cidr: a local CIDR, `0.0.0.0/0` is any. This could be used to filter destinations when using unsafe_routes.
# Default is `any` unless the certificate contains subnets and then the default is the ip issued in the certificate
# if `default_local_cidr_any` is false, otherwise its `any`.
# ca_name: An issuing CA name
# ca_sha: An issuing CA shasum
outbound:
# Allow all outbound traffic from this node
- port: any
proto: any
host: any
inbound:
# Allow icmp between any nebula hosts
- port: any
proto: icmp
host: any
# Allow tcp/443 from any host with BOTH laptop and home group
- port: 443
proto: tcp
groups:
- laptop
- home
# Expose a subnet (unsafe route) to hosts with the group remote_client
# This example assume you have a subnet of 192.168.100.1/24 or larger encoded in the certificate
- port: 8080
proto: tcp
group: remote_client
local_cidr: 192.168.100.1/24
Lighthouse config.yml
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/host.crt
key: /etc/nebula/host.key
static_host_map:
lighthouse:
am_lighthouse: true
interval: 60
listen:
host: 0.0.0.0
port: 4242
punchy:
punch: true
cipher: aes
relay:
#relays:
#- 192.168.100.1
#- <other Nebula VPN IPs of hosts used as relays to access me>
am_relay: true
use_relays: true
tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
logging:
level: info
format: text
firewall:
outbound_action: drop
inbound_action: drop
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
Hosts config.yml
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/host.crt
key: /etc/nebula/host.key
static_host_map:
'192.168.100.1': ['api.your.run:4242']
lighthouse:
am_lighthouse: false
interval: 60
hosts:
- "192.168.100.1"
listen:
# To listen on both any ipv4 and ipv6 use "::"
host: 0.0.0.0
port: 0
punchy:
punch: true
cipher: aes
relay:
am_relay: false
use_relays: true
tun:
disabled: false
dev: nebula1
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
logging:
level: info
format: text
firewall:
outbound_action: drop
inbound_action: drop
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
# 일부 서버에서 HTTPS 호스팅을 위해 필요.
- port: 443
proto: tcp
host: any
# kubectl 에서 사용하는 6443 포트
- port: 6443
proto: tcp
host: any
Troubleshooting
특정 Node의 서비스 재시작 이후 접속 안됨
다음과 같을 때:
- NodeA - 현재 내 로컬 PC
- NodeB - 서버 PC
NodeB 의 설정을 변경한 후 서비스 재시작 했는데 NodeA 에서 NodeB 로 ping 이 갑자기 안간다면... NodeA 도 재시작 해라!!!!! UDP 라서 연결 지향이 안되는게 원인일 것으로 추정함. <- 확인 필요. 어쨋든 관련 노드 전부 서비스 재시작 해라.
See also
- Overlay network
- TailScale
- Headscale - TailScale 서버의 오픈소스 구현체
- Tunneling protocol (Tunneling)
- VPN
- P2P
- UDP Hole Punching
- ngrok - 로컬 개발 환경에서 인터넷을 통해 웹 애플리케이션에 안전하게 접근할 수 있도록 해주는 도구입니다.