aboutsummaryrefslogtreecommitdiffstats
path: root/docs/ip-request.md
blob: 1852bae98cc064c6c316450de2629800ef45c3fa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT
DRAFT                                     DRAFT
DRAFT                                     DRAFT
DRAFT             2019-09-27              DRAFT
DRAFT                                     DRAFT
DRAFT                                     DRAFT
DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT

# Dynamic IP address allocation

This document describes version 1 of the wg-dynamic `request_ip`
command.

See protocol.md for a general description of the protocol.


## Server

The wg-dynamic server is a daemon responsible for handing out IP
addresses in form of leases to wg-dynamic clients requesting them.

Unless the client asks for a specific address, one is picked uniformly
random from a pool of free addresses and is handed out to wg-dynamic
clients upon request.

A pool of available addresses, both IPv4 and IPv6, is being maintained
by the server. The pool is populated with the list of addresses being
routed over the wg interface and updated as leases are being granted
and expire. The first and last IPv4 addresses of an address block with
a prefix length less than 31 bits are not handed out.

A request for a specific IP address is granted if the address is
present in the pool and the server plans on keeping it in the pool for
the lifetime of the lease.

A request not including an IP address should result in a lease for one
IPv4 address and one IPv6 address. The server is allowed to impose
rate limiting on the churn of addresses granted to a given client.

A given client is at any given time granted at most one IPv4 address
and at most one IPv6 address.

A lease is valid for a configured amount of time, by default 3600
seconds.


## Client

The wg-dynamic client is a daemon responsible for requesting IP
address leases from a wg-dynamic server, for a given wg
interface. Requests for leases are sent over the clients wg interface
to a server on a well known IPv6 link local address and well known low
TCP port. The source port used MUST be the same as the well known
server port.

At any given time, a client has one or zero leases. A lease has one or
zero IPv4 addresses and one or zero IPv6 addresses.

A client starts refreshing its lease 300 seconds (plus/minus a random
jitter, 0s-30s) before the lease runs out. It keeps refreshing its
lease until it has one with a lifetime longer than 300 seconds.

### Security

A client MUST send requests from an IPv6 link local address with
netmask 128 and with the scope of the wg interface. It MUST use the
same low TCP port as being used by the server. This way wg-dynamic
requests are guaranteed to be sent only to and received only from the
configured wg-dynamic server endpoint and only sent by a process with
permissions to bind to a low port.

TODO: no routing information is being accepted by clients, eg only
configuring /32 and /128 addresses

## Protocol

A client requests IP address leasees by sending a request\_ip
command. The request\_ip command has the following optional attribute:

- ipv4 (optional)

  Omitting this attribute indicates that the client is fine with any
  IPv4 address and gets an address by random, given that the IPv4 pool
  is not exhausted.

  Sending this attribute with an IPv4 address in CIDR notation as its
  value means that the client would like to have this particular
  address granted.

  Sending this attribute without a value ("ipv4=") means that the
  client does not want an IPv4 address and that any IPv4 address being
  allocated for it should be released.

- ipv6 (optional)

  Omitting this attribute indicates that the client is fine with any
  IPv6 address and gets an address by random, given that the IPv6 pool
  is not exhausted.

  Sending this attribute with an IPv6 address in CIDR notation as its
  value means that the client would like to have this particular
  address granted.

  Sending this attribute without a value ("ipv6=") means that the
  client does not want an IPv6 address and that any IPv6 address being
  allocated for it should be released.


The server response to a request\_ip command contains an errno
attribute and, if the request was succesful, up to three attributes
containing the result:

- ipv4

  IPv4 address for the client to use. A server MUST offer IPv4
  addresses with a prefix length of 32 bits and a client MUST refuse an
  address with a shorter prefix.

- ipv6

  IPv6 address for the client to use. A server MUST offer IPv6
  addresses with a prefix length of 128 bits and a client MUST refuse
  an address with a shorter prefix.

- leasestart

  The start time of the lease, in seconds since the epoch.

  A client receiving a response with a leasestart that deviates from
  current time of the client by more than 15 seconds MUST use current
  time instead of leasestart.

- leasetime

  The number of seconds that this lease is valid, starting from
  leasestart.

  MUST be the current time of the server.

- errno

  Errno is 0 for a successful operation.

A point in time is expressed as seconds since the epoch (1970-01-01
00:00 UTC). When this document talks about current time, the current
time of the computers clock in UTC is what's being refered to.

If the request fails, errno is != 0 and an errmsg attribute is the
only other attribute in the response:

- errno

  A positive integer indicating what made the request fail. The
  following error codes are defined:

  - 1: Undefined internal error

- errmsg

  A text suitable for human consumption, describing what made the
  request fail.

### Examples

#### Example 1

Client asking for any IPv4 address and any IPv6 address, receiving
both. This results in two leases being recorded by the client, one per
address.

client -> server request

    request_ip=1

server -> client response

    request_ip=1
    ipv4=192.168.47.11/32
    ipv6=fd00::4711/128
    leasestart=1569234893
    leasetime=1800
    errno=0

#### Example 2

Client asking for a specific IPv4 address and a specific IPv6 address,
receiving both.

client -> server request

    request_ip=1
    ipv4=192.168.47.11/32
    ipv6=fd00::4711/128

server -> client response

    request_ip=1
    ipv4=192.168.47.11/32
    ipv6=fd00::4711/128
    leasestart=1569236593
    leasetime=1800
    errno=0

#### Example 3

Client asking for a specific IPv4 address and a specific IPv6 address,
receiving none because both the IPv4 and IPv6 pools are empty.

client -> server request

    request_ip=1
    ipv4=192.168.47.11/32
    ipv6=fd00::4711/128

server -> client response

    request_ip=1
    errno=0

#### Example 4

Client asking for any IPv4 address and a specific IPv6 address,
receiving no IPv4 address because that pool is empty and another IPv6
because the requested address is not free.

client -> server request

    request_ip=1
    ipv6=fd00::4711/128

server -> client response

    request_ip=1
    ipv6=fd00::42/128
    leasestart=1569273827
    leasetime=1800
    errno=0

#### Example 5

Client asking for any IPv4 address and no IPv6 address, receiving an
IPv4 address and no IPv6 address. If the client did have an IPv6
address allocated at the time of the request it's now been released.

client -> server request

    request_ip=1
    ipv6=

server -> client response

    request_ip=1
    ipv4=192.168.47.22/32
    errno=0