メインコンテンツまでスキップ

API v1alpha1

routerd の config は Kubernetes 風のリソース形状を使います。

  • apiVersion
  • kind
  • metadata.name
  • spec
  • 必要に応じて status

API Groups

  • routerd.net/v1alpha1: top-level Router
  • net.routerd.net/v1alpha1: network resources
  • firewall.routerd.net/v1alpha1: firewall resources
  • system.routerd.net/v1alpha1: local system resources
  • plugin.routerd.net/v1alpha1: plugin manifests

主なリソース

  • Interface
  • PPPoEInterface
  • IPv4StaticAddress
  • IPv4DHCPAddress
  • IPv4DHCPServer
  • IPv4DHCPScope
  • HealthCheck
  • IPv4DefaultRoutePolicy
  • IPv4SourceNAT
  • IPv4PolicyRoute
  • IPv4PolicyRouteSet
  • IPv4ReversePathFilter
  • PathMTUPolicy
  • Zone
  • FirewallPolicy
  • ExposeService
  • IPv6DHCPAddress
  • IPv6PrefixDelegation
  • IPv6DelegatedAddress
  • IPv6DHCPServer
  • IPv6DHCPScope
  • SelfAddressPolicy
  • DNSConditionalForwarder
  • DSLiteTunnel
  • LogSink
  • NTPClient
  • Hostname
  • Sysctl

Interface Ownership

Interface.spec.managed は、routerd がそのinterfaceを変更してよいかを示します。

  • managed: false: observe と alias 解決だけを行い、link/address state は変更しません。
  • managed: true: routerd がそのinterfaceを管理できます。ただし cloud-init や netplan の既存所有が見える場合は、いきなり奪わず RequiresAdoption として計画に出します。

実機上の所有関係は artifact intent と、取り込み済みリソースについては /var/lib/routerd/artifacts.json のローカル台帳で扱います。各リソース共通の reconcile と orphan cleanup の考え方は リソース所有 を参照してください。

PPPoEInterface

PPPoEInterface は、別の Interface の上に PPPoE interface を作るリソースです。Linux では pppd/rp-pppoe の peer 設定、CHAP/PAP secrets、任意の systemd unit を生成します。

apiVersion: net.routerd.net/v1alpha1
kind: PPPoEInterface
metadata:
name: wan-ppp
spec:
interface: wan-ether
ifname: ppp0
username: user@example.jp
passwordFile: /usr/local/etc/routerd/pppoe-password
defaultRoute: true
usePeerDNS: true
managed: true
mtu: 1492
mru: 1492

interface は下位の Ethernet Interface を参照します。ifname は省略すると ppp-<metadata.name> ですが、Linux の interface name 制限に合わせて15文字以内である必要があります。 passwordpasswordFile はどちらか一方だけを指定します。認証情報を main YAML に置かないため、通常は passwordFile を推奨します。

managed: true の場合、routerd は routerd-pppoe-<name>.service を enable/start します。managed: false の場合は設定ファイルだけを生成し、unit は起動しません。

LogSink

system.routerd.net/v1alpha1LogSink は、routerd の内部イベントをどこへ出すかを宣言します。

ローカルの journald/syslog に出す場合:

apiVersion: system.routerd.net/v1alpha1
kind: LogSink
metadata:
name: local-syslog
spec:
type: syslog
minLevel: info
syslog:
facility: local6
tag: routerd

信頼済みローカル log plugin に出す場合:

apiVersion: system.routerd.net/v1alpha1
kind: LogSink
metadata:
name: external-log
spec:
type: plugin
minLevel: warning
plugin:
path: /usr/local/libexec/routerd/log-sinks/example
timeout: 5s

enabled は省略時 trueminLevel は省略時 info です。syslog.facility は省略時 local6syslog.tag は省略時 routerd です。 remote syslog へ送る場合は syslog.networksyslog.address を指定します。例: network: udpaddress: syslog.example.net:514

NTPClient

system.routerd.net/v1alpha1NTPClient はlocal NTP clientを宣言します。初期実装では systemd-timesyncd とstatic server指定を管理します。

apiVersion: system.routerd.net/v1alpha1
kind: NTPClient
metadata:
name: system-time
spec:
provider: systemd-timesyncd
managed: true
source: static
interface: wan
servers:
- pool.ntp.org

interface を指定した場合、routerd は systemd-networkd のlink別 NTP= としてそのinterfaceにNTP serverを設定します。省略時は systemd-timesyncd のglobal serverとして設定します。

Sysctl

system.routerd.net/v1alpha1Sysctl は kernel parameter を宣言します。

apiVersion: system.routerd.net/v1alpha1
kind: Sysctl
metadata:
name: ipv4-forwarding
spec:
key: net.ipv4.ip_forward
value: "1"
runtime: true
persistent: false

現在 runtime: true は実行中kernel値へ反映します。persistent: true は sysctl.d や rc.conf への永続化用として予約されています。

SelfAddressPolicy

SelfAddressPolicydnsSource: self がどのlocal addressを選ぶかを定義します。LAN用 delegated address と DS-Lite source address のように、同じinterfaceに複数のIPv6 addressがある場合の選択を明示できます。

apiVersion: net.routerd.net/v1alpha1
kind: SelfAddressPolicy
metadata:
name: lan-ipv6-self
spec:
addressFamily: ipv6
candidates:
- source: delegatedAddress
delegatedAddress: lan-ipv6-pd-address
addressSuffix: "::3"
- source: interfaceAddress
interface: lan
matchSuffix: "::3"
- source: interfaceAddress
interface: lan
ordinal: 1

IPv6DHCPScope から参照します。

spec:
dnsSource: self
selfAddressPolicy: lan-ipv6-self

candidate は上から順番に評価され、最初に解決できたaddressを使います。省略時は、IPv6 DHCP scope の IPv6DelegatedAddress.addressSuffix を使った delegated address、suffix一致の観測済みaddress、観測済みglobal addressの先頭、という順番になります。

IPv6 Prefix Delegation

IPv6PrefixDelegation は uplink interface で DHCPv6-PD を要求します。IPv6DelegatedAddress は delegated prefix と固定suffixを組み合わせて downstream interface のIPv6 addressを作ります。

apiVersion: net.routerd.net/v1alpha1
kind: IPv6PrefixDelegation
metadata:
name: wan-pd
spec:
interface: wan
client: networkd
profile: ntt-hgw-lan-pd
prefixLength: 60
apiVersion: net.routerd.net/v1alpha1
kind: IPv6DelegatedAddress
metadata:
name: lan-ipv6-pd-address
spec:
prefixDelegation: wan-pd
interface: lan
subnetID: "0"
addressSuffix: "::3"
announce: true

Linux では systemd-networkd drop-in を /etc/systemd/network/10-netplan-<ifname>.network.d/ にrenderします。

NTT向けprofile:

  • ntt-ngn-direct-hikari-denwa
  • ntt-hgw-lan-pd

どちらも現時点では IA_PD のみを前提にし、prefix hint は明示がなければ /60 を使います。

DHCP と DNS

IPv4DHCPServer は DHCPv4 server instance、IPv4DHCPScope は interface と address pool / options を定義します。

apiVersion: net.routerd.net/v1alpha1
kind: IPv4DHCPServer
metadata:
name: dhcp4
spec:
server: dnsmasq
managed: true
listenInterfaces:
- lan
dns:
enabled: true
upstreamSource: dhcp4
upstreamInterface: wan
cacheSize: 1000
apiVersion: net.routerd.net/v1alpha1
kind: IPv4DHCPScope
metadata:
name: lan-dhcp4
spec:
server: dhcp4
interface: lan
rangeStart: 192.168.160.100
rangeEnd: 192.168.160.199
leaseTime: 12h
routerSource: interfaceAddress
dnsSource: self
authoritative: true

IPv6DHCPServerIPv6DHCPScope は dnsmasq による DHCPv6/RA を扱います。dnsSource: self は delegated LAN IPv6 address、たとえば pd-prefix::3 をDNS serverとして広告します。

dnsmasq の RA が有効な場合、routerd は同じ IPv6 DNS server list を DHCPv6 DNS と RA RDNSS の両方に使います。Android は DHCPv6 client として期待せず、SLAAC/RDNSS client として扱う方が自然です。

dnsmasq backendでは listenInterfaces がサービス提供interfaceのallow-listです。scopeはserver側の listenInterfaces に含まれるinterfaceにだけbindできます。指定されていないinterfaceは except-interface としてrenderされるため、WANであってもLANであっても明示しない限りサービスしません。

HealthCheck と IPv4DefaultRoutePolicy

HealthCheck は疎通確認を宣言します。interval を省略した場合のデフォルトは 60s です。経路切替が鋭敏になりすぎないよう、短い間隔は明示した場合だけ使います。

apiVersion: net.routerd.net/v1alpha1
kind: HealthCheck
metadata:
name: dslite-v4
spec:
type: ping
role: next-hop
targetSource: dsliteRemote
interface: transix-a

role は、その確認が運用上何を意味するかを表します。これ自体は送出するパケットを変えませんが、経路ポリシーや状態出力を読みやすくします。

  • link: インターフェースの存在、キャリア、管理状態。
  • next-hop: ゲートウェイ、AFTR、トンネル終端など近傍の転送依存先。
  • internet: 公開先への ping や TCP 接続など、インターネット全体の到達性。
  • service: DNS 解決、DHCP、AFTR FQDN 解決、PPPoE セッションなどサービス固有の依存先。
  • policy: 経路候補を選んでよいかを示す集約結果。

省略時の rolenext-hop です。これは現在の targetSource: auto の動きと一致します。

IPv4DefaultRoutePolicy は、healthy な候補のうち priority が最小のものを active にします。候補は直接interfaceを指すか、IPv4PolicyRouteSetrouteSet で参照します。直接候補は専用のrouting tableとfirewall markを持ちます。新規flowはactiveな直接候補へmarkされ、既存flowはその候補がhealthyな間はconntrack markで同じ経路を維持します。旧候補がunhealthyになった場合は、該当flowも現在のactive候補へmarkし直します。

active候補が routeSet を参照する場合、routerd は新規flowをmarkせず、参照先の IPv4PolicyRouteSet がhashでtargetを選べるようにします。healthyなroute set targetのconntrack markは維持します。失敗した候補の古いmarkはclearし、route setに再選出させます。

target を省略すると targetSource: auto として近傍の確認先を選びます。DS-Lite は AFTR の IPv6 アドレス、通常interface/PPPoE はそのinterfaceの IPv4 default gateway を確認します。これは標準では next-hop 確認です。IPv4 Internet 全体の到達性を見たい場合は、明示的なstatic IPv4 targetを持つ role: internet の別 HealthCheck を設定します。将来的には role: policy の集約確認で、複数の下位確認をまとめて経路候補の選択可否にできます。候補に healthCheck を指定しない場合、その候補は常に up として扱います。

apiVersion: net.routerd.net/v1alpha1
kind: IPv4DefaultRoutePolicy
metadata:
name: default-v4
spec:
mode: priority
sourceCIDRs:
- 192.168.160.0/24
destinationCIDRs:
- 0.0.0.0/0
candidates:
- name: dslite
routeSet: lan-dslite-balance
priority: 10
healthCheck: dslite-v4
- name: pppoe
interface: wan-pppoe
gatewaySource: none
priority: 20
table: 111
mark: 273
routeMetric: 60
healthCheck: pppoe-v4
- name: dhcp4
interface: wan
gatewaySource: dhcp4
priority: 30
table: 112
mark: 274
routeMetric: 100
healthCheck: wan-dhcp4-v4

IPv4 Source NAT

IPv4SourceNAT は outbound NAT を宣言します。Linux では nftables にrenderされます。

apiVersion: net.routerd.net/v1alpha1
kind: IPv4SourceNAT
metadata:
name: lan-to-transix-a
spec:
outboundInterface: transix-a
sourceCIDRs:
- 192.168.160.0/24
translation:
type: address
address: 192.0.0.2
portMapping:
type: range
start: 1024
end: 65535

outboundInterfaceInterfacePPPoEInterface、または DSLiteTunnel を参照できます。

IPv4PolicyRouteSet

IPv4PolicyRouteSet は、source/destination address をhashして複数のpolicy route targetへ分散します。Linux では nftables mark、conntrack mark、ip rule、専用routing tableを使います。

apiVersion: net.routerd.net/v1alpha1
kind: IPv4PolicyRouteSet
metadata:
name: lan-dslite-balance
spec:
mode: hash
hashFields:
- sourceAddress
- destinationAddress
sourceCIDRs:
- 192.168.160.0/24
destinationCIDRs:
- 0.0.0.0/0
targets:
- name: transix-a
outboundInterface: transix-a
table: 100
priority: 10000
mark: 256
- name: transix-b
outboundInterface: transix-b
table: 101
priority: 10001
mark: 257

同じflowは conntrack mark によって同じtargetへ固定されます。

IPv4ReversePathFilter

policy routing や複数DS-Lite tunnelでは、Linux rp_filter が正当な戻り通信を落とす場合があります。IPv4ReversePathFilter はそれをconfigで制御します。

apiVersion: net.routerd.net/v1alpha1
kind: IPv4ReversePathFilter
metadata:
name: rp-filter-transix-a
spec:
target: interface
interface: transix-a
mode: disabled

targetalldefaultinterfacemodedisabledstrictloose です。

PathMTUPolicy

PathMTUPolicy は、あるインターフェースから複数の上流インターフェースへ出ていく通信の実効 MTU を決めます。その MTU を IPv6 RA で LAN クライアントへ広告し、IPv4/IPv6 の forward 通信に TCP MSS clamp を入れられます。

apiVersion: net.routerd.net/v1alpha1
kind: PathMTUPolicy
metadata:
name: lan-wan-mtu
spec:
fromInterface: lan
toInterfaces:
- wan
- transix
mtu:
source: minInterface
ipv6RA:
enabled: true
scope: lan-dhcp6
tcpMSSClamp:
enabled: true
families:
- ipv4
- ipv6

mtu.source: minInterfacetoInterfaces の MTU の最小値を使います。通常の Interface は現時点では 1500PPPoEInterface1492DSLiteTunnel1454 を既定値として扱います。各リソースで mtu を指定している場合はそれを使います。mtu.source: static の場合は mtu.value を使います。

ipv6RA.enabled が true の場合、ipv6RA.scopeIPv6DHCPScope を参照します。dnsmasq には ra-param=ens19,1454 のような RA MTU option を出力します。

tcpMSSClamp.enabled が true の場合、routerd は nftables の forward chain に MSS clamp rule を出力します。MSS は実効 MTU から固定で計算します。IPv4 は 40 bytes、IPv6 は 60 bytes を引きます。families を省略した場合は ipv4ipv6 の両方を有効にします。

最小 Firewall

Firewall リソースは firewall.routerd.net/v1alpha1 を使います。最初の firewall API は汎用ルール言語にせず、家庭用ルーターとしての安全な標準動作とサービス公開に絞ります。

  • Zone: lanwan のように、ルーターのインターフェース集合へ名前を付けます。
  • FirewallPolicy: home-router プリセットと input/forward の標準動作を宣言します。
  • ExposeService: 内部 IPv4 サービスを DNAT と forward 許可ルールで公開します。

home-router プリセットは、input/forward の標準 drop、invalid drop、established/related accept、loopback input accept、lan/wan zone がある場合の LAN から WAN への forward 許可、設定された routerAccess zone からの SSH/DNS/DHCP のみ許可、を出力します。

apiVersion: firewall.routerd.net/v1alpha1
kind: FirewallPolicy
metadata:
name: default-home
spec:
preset: home-router
input:
default: drop
forward:
default: drop
routerAccess:
ssh:
fromZones:
- lan
wan:
enabled: false
dns:
fromZones:
- lan
dhcp:
fromZones:
- lan

ExposeService は IPv4 port publish の最初の構成要素です。sources を指定すると、その送信元 IPv4 prefix だけを許可します。hairpin はリソース形状として受け付けますが、外側アドレスの選出モデルがまだ無いため、最初の renderer は external-address hairpin ルールを合成しません。

apiVersion: firewall.routerd.net/v1alpha1
kind: ExposeService
metadata:
name: nas-https
spec:
family: ipv4
fromZone: wan
viaInterface: wan-pppoe
protocol: tcp
externalPort: 443
internalAddress: 192.168.160.20
internalPort: 443
sources:
- 203.0.113.0/24
hairpin: true

DNSConditionalForwarder

特定domainだけ別DNSへforwardします。DS-Lite AFTR名のようにprovider DNSでしか正しいAAAAが返らない名前に使います。

apiVersion: net.routerd.net/v1alpha1
kind: DNSConditionalForwarder
metadata:
name: transix-aftr
spec:
domain: gw.transix.jp
upstreamSource: static
upstreamServers:
- 2404:1a8:7f01:a::3
- 2404:1a8:7f01:b::3

DSLiteTunnel

DSLiteTunnel は DS-Lite B4 tunnel を宣言します。Linux では ip -6 tunnelipip6 tunnel を作ります。

apiVersion: net.routerd.net/v1alpha1
kind: DSLiteTunnel
metadata:
name: transix-a
spec:
interface: wan
tunnelName: ds-transix-a
aftrFQDN: gw.transix.jp
aftrDNSServers:
- 2404:1a8:7f01:a::3
- 2404:1a8:7f01:b::3
aftrAddressOrdinal: 1
aftrAddressSelection: ordinalModulo
localAddressSource: delegatedAddress
localDelegatedAddress: lan-ipv6-pd-address
localAddressSuffix: "::100"
mtu: 1454

remoteAddress を省略すると、aftrFQDN のAAAAを引きます。AAAAは文字列昇順にsortされ、aftrAddressOrdinal で1始まりの番号を選びます。

aftrAddressSelection:

  • ordinal: 指定番号が存在しなければ失敗します。
  • ordinalModulo: record数で折り返します。

AFTR record数が減っても複数tunnelを維持したい場合、localAddressSuffix はtunnelごとに分けてください。そうしないと同じ (local, remote) の tunnel が重複する可能性があります。