OpenVPN
occ.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "syshead.h"
29 
30 #include "occ.h"
31 #include "forward.h"
32 #include "memdbg.h"
33 
34 
35 /*
36  * This random string identifies an OpenVPN
37  * Configuration Control packet.
38  * It should be of sufficient length and randomness
39  * so as not to collide with other tunnel data.
40  *
41  * The OCC protocol is as follows:
42  *
43  * occ_magic -- (16 octets)
44  *
45  * type [OCC_REQUEST | OCC_REPLY] (1 octet)
46  * null terminated options string if OCC_REPLY (variable)
47  *
48  * When encryption is used, the OCC packet
49  * is encapsulated within the encrypted
50  * envelope.
51  *
52  * OCC_STRING_SIZE must be set to sizeof (occ_magic)
53  */
54 
55 const uint8_t occ_magic[] = {
56  0x28, 0x7f, 0x34, 0x6b, 0xd4, 0xef, 0x7a, 0x81,
57  0x2d, 0x56, 0xb8, 0xd3, 0xaf, 0xc5, 0x45, 0x9c
58 };
59 
60 static const struct mtu_load_test mtu_load_test_sequence[] = {
61 
62  {OCC_MTU_LOAD_REQUEST, -1000},
63  {OCC_MTU_LOAD, -1000},
64  {OCC_MTU_LOAD_REQUEST, -1000},
65  {OCC_MTU_LOAD, -1000},
66  {OCC_MTU_LOAD_REQUEST, -1000},
67  {OCC_MTU_LOAD, -1000},
68 
69  {OCC_MTU_LOAD_REQUEST, -750},
70  {OCC_MTU_LOAD, -750},
71  {OCC_MTU_LOAD_REQUEST, -750},
72  {OCC_MTU_LOAD, -750},
73  {OCC_MTU_LOAD_REQUEST, -750},
74  {OCC_MTU_LOAD, -750},
75 
76  {OCC_MTU_LOAD_REQUEST, -500},
77  {OCC_MTU_LOAD, -500},
78  {OCC_MTU_LOAD_REQUEST, -500},
79  {OCC_MTU_LOAD, -500},
80  {OCC_MTU_LOAD_REQUEST, -500},
81  {OCC_MTU_LOAD, -500},
82 
83  {OCC_MTU_LOAD_REQUEST, -400},
84  {OCC_MTU_LOAD, -400},
85  {OCC_MTU_LOAD_REQUEST, -400},
86  {OCC_MTU_LOAD, -400},
87  {OCC_MTU_LOAD_REQUEST, -400},
88  {OCC_MTU_LOAD, -400},
89 
90  {OCC_MTU_LOAD_REQUEST, -300},
91  {OCC_MTU_LOAD, -300},
92  {OCC_MTU_LOAD_REQUEST, -300},
93  {OCC_MTU_LOAD, -300},
94  {OCC_MTU_LOAD_REQUEST, -300},
95  {OCC_MTU_LOAD, -300},
96 
97  {OCC_MTU_LOAD_REQUEST, -200},
98  {OCC_MTU_LOAD, -200},
99  {OCC_MTU_LOAD_REQUEST, -200},
100  {OCC_MTU_LOAD, -200},
101  {OCC_MTU_LOAD_REQUEST, -200},
102  {OCC_MTU_LOAD, -200},
103 
104  {OCC_MTU_LOAD_REQUEST, -150},
105  {OCC_MTU_LOAD, -150},
106  {OCC_MTU_LOAD_REQUEST, -150},
107  {OCC_MTU_LOAD, -150},
108  {OCC_MTU_LOAD_REQUEST, -150},
109  {OCC_MTU_LOAD, -150},
110 
111  {OCC_MTU_LOAD_REQUEST, -100},
112  {OCC_MTU_LOAD, -100},
113  {OCC_MTU_LOAD_REQUEST, -100},
114  {OCC_MTU_LOAD, -100},
115  {OCC_MTU_LOAD_REQUEST, -100},
116  {OCC_MTU_LOAD, -100},
117 
118  {OCC_MTU_LOAD_REQUEST, -50},
119  {OCC_MTU_LOAD, -50},
120  {OCC_MTU_LOAD_REQUEST, -50},
121  {OCC_MTU_LOAD, -50},
122  {OCC_MTU_LOAD_REQUEST, -50},
123  {OCC_MTU_LOAD, -50},
124 
126  {OCC_MTU_LOAD, 0},
128  {OCC_MTU_LOAD, 0},
130  {OCC_MTU_LOAD, 0},
131 
132  {OCC_MTU_REQUEST, 0},
133  {OCC_MTU_REQUEST, 0},
134  {OCC_MTU_REQUEST, 0},
135  {OCC_MTU_REQUEST, 0},
136  {OCC_MTU_REQUEST, 0},
137  {OCC_MTU_REQUEST, 0},
138  {OCC_MTU_REQUEST, 0},
139  {OCC_MTU_REQUEST, 0},
140  {OCC_MTU_REQUEST, 0},
141  {OCC_MTU_REQUEST, 0},
142 
143  {-1, 0}
144 };
145 
146 void
148 {
149  if (++c->c2.occ_n_tries >= OCC_N_TRIES)
150  {
151  if (c->options.ce.remote)
152  {
153  /*
154  * No OCC_REPLY from peer after repeated attempts.
155  * Give up.
156  */
157  msg(D_SHOW_OCC,
158  "NOTE: failed to obtain options consistency info from peer -- "
159  "this could occur if the remote peer is running a version of "
161  " before 1.5-beta8 or if there is a network connectivity problem, and will not necessarily prevent "
163  " from running (" counter_format " bytes received from peer, " counter_format
164  " bytes authenticated data channel traffic) -- you can disable the options consistency "
165  "check with --disable-occ.",
166  c->c2.link_read_bytes,
168  }
170  }
171  else
172  {
173  c->c2.occ_op = OCC_REQUEST;
174 
175  /*
176  * If we don't hear back from peer, send another
177  * OCC_REQUEST in OCC_INTERVAL_SECONDS.
178  */
180  }
181 }
182 
183 void
185 {
186  if (connection_established(c))
187  {
188  const struct mtu_load_test *entry;
189 
190  if (!c->c2.occ_mtu_load_n_tries)
191  {
192  msg(M_INFO,
193  "NOTE: Beginning empirical MTU test -- results should be available in 3 to 4 minutes.");
194  }
195 
197  if (entry->op >= 0)
198  {
199  c->c2.occ_op = entry->op;
200  size_t payload_size = frame_calculate_payload_size(&c->c2.frame,
201  &c->options, &c->c1.ks.key_type);
202  size_t header_size = frame_calculate_protocol_header_size(&c->c1.ks.key_type, &c->options, false);
203 
204  c->c2.occ_mtu_load_size = payload_size + header_size;
205  }
206  else
207  {
208  msg(M_INFO,
209  "NOTE: failed to empirically measure MTU (requires " PACKAGE_NAME " 1.5 or higher at other end of connection).");
211  c->c2.occ_mtu_load_n_tries = 0;
212  }
213  }
214 }
215 
216 void
218 {
219  bool doit = false;
220 
221  c->c2.buf = c->c2.buffers->aux_buf;
222  ASSERT(buf_init(&c->c2.buf, c->c2.frame.buf.headroom));
225 
226  switch (c->c2.occ_op)
227  {
228  case OCC_REQUEST:
229  if (!buf_write_u8(&c->c2.buf, OCC_REQUEST))
230  {
231  break;
232  }
233  dmsg(D_PACKET_CONTENT, "SENT OCC_REQUEST");
234  doit = true;
235  break;
236 
237  case OCC_REPLY:
238  if (!c->c2.options_string_local)
239  {
240  break;
241  }
242  if (!buf_write_u8(&c->c2.buf, OCC_REPLY))
243  {
244  break;
245  }
246  if (!buf_write(&c->c2.buf, c->c2.options_string_local,
247  strlen(c->c2.options_string_local) + 1))
248  {
249  break;
250  }
251  dmsg(D_PACKET_CONTENT, "SENT OCC_REPLY");
252  doit = true;
253  break;
254 
255  case OCC_MTU_REQUEST:
256  if (!buf_write_u8(&c->c2.buf, OCC_MTU_REQUEST))
257  {
258  break;
259  }
260  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_REQUEST");
261  doit = true;
262  break;
263 
264  case OCC_MTU_REPLY:
265  if (!buf_write_u8(&c->c2.buf, OCC_MTU_REPLY))
266  {
267  break;
268  }
269  if (!buf_write_u16(&c->c2.buf, c->c2.max_recv_size_local))
270  {
271  break;
272  }
273  if (!buf_write_u16(&c->c2.buf, c->c2.max_send_size_local))
274  {
275  break;
276  }
277  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_REPLY");
278  doit = true;
279  break;
280 
283  {
284  break;
285  }
286  if (!buf_write_u16(&c->c2.buf, c->c2.occ_mtu_load_size))
287  {
288  break;
289  }
290  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_LOAD_REQUEST");
291  doit = true;
292  break;
293 
294  case OCC_MTU_LOAD:
295  {
296  int need_to_add;
297 
298  if (!buf_write_u8(&c->c2.buf, OCC_MTU_LOAD))
299  {
300  break;
301  }
302  size_t proto_hdr, payload_hdr;
303  const struct key_type *kt = &c->c1.ks.key_type;
304 
305  /* OCC message have comp/fragment headers but not ethernet headers */
306  payload_hdr = frame_calculate_payload_overhead(0, &c->options, kt);
307 
308  /* Since we do not know the payload size we just pass 0 as size here */
309  proto_hdr = frame_calculate_protocol_header_size(kt, &c->options, false);
310 
311  need_to_add = min_int(c->c2.occ_mtu_load_size, c->c2.frame.buf.payload_size)
313  - sizeof(uint8_t) /* occ opcode */
314  - payload_hdr
315  - proto_hdr;
316 
317  while (need_to_add > 0)
318  {
319  /*
320  * Fill the load test packet with pseudo-random bytes.
321  */
322  if (!buf_write_u8(&c->c2.buf, get_random() & 0xFF))
323  {
324  break;
325  }
326  --need_to_add;
327  }
328  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_LOAD min_int(%d,%d)-%d-%d-%d-%d) size=%d",
332  (int) sizeof(uint8_t),
333  (int) payload_hdr,
334  (int) proto_hdr,
335  BLEN(&c->c2.buf));
336  doit = true;
337  }
338  break;
339 
340  case OCC_EXIT:
341  if (!buf_write_u8(&c->c2.buf, OCC_EXIT))
342  {
343  break;
344  }
345  dmsg(D_PACKET_CONTENT, "SENT OCC_EXIT");
346  doit = true;
347  break;
348  }
349 
350  if (doit)
351  {
352  /*
353  * We will treat the packet like any other outgoing packet,
354  * compress, encrypt, sign, etc.
355  */
356  encrypt_sign(c, true);
357  }
358 
359  c->c2.occ_op = -1;
360 }
361 
362 void
364 {
366  switch (buf_read_u8(&c->c2.buf))
367  {
368  case OCC_REQUEST:
369  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_REQUEST");
370  c->c2.occ_op = OCC_REPLY;
371  break;
372 
373  case OCC_MTU_REQUEST:
374  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_REQUEST");
375  c->c2.occ_op = OCC_MTU_REPLY;
376  break;
377 
379  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_LOAD_REQUEST");
381  if (c->c2.occ_mtu_load_size >= 0)
382  {
383  c->c2.occ_op = OCC_MTU_LOAD;
384  }
385  break;
386 
387  case OCC_REPLY:
388  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_REPLY");
389  if (c->options.occ && !TLS_MODE(c) && c->c2.options_string_remote)
390  {
391  if (!options_cmp_equal_safe((char *) BPTR(&c->c2.buf),
393  c->c2.buf.len))
394  {
395  options_warning_safe((char *) BPTR(&c->c2.buf),
397  c->c2.buf.len);
398  }
399  }
401  break;
402 
403  case OCC_MTU_REPLY:
404  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_REPLY");
407  if (c->options.mtu_test
408  && c->c2.max_recv_size_remote > 0
409  && c->c2.max_send_size_remote > 0)
410  {
411  msg(M_INFO, "NOTE: Empirical MTU test completed [Tried,Actual] local->remote=[%d,%d] remote->local=[%d,%d]",
416  if (!c->options.ce.fragment
417  && (proto_is_dgram(c->options.ce.proto))
421  {
422  msg(M_INFO, "NOTE: This connection is unable to accommodate a UDP packet size of %d. Consider using --fragment or --mssfix options as a workaround.",
424  }
425  }
427  break;
428 
429  case OCC_EXIT:
430  dmsg(D_STREAM_ERRORS, "OCC exit message received by peer");
431  register_signal(c->sig, SIGUSR1, "remote-exit");
432  break;
433  }
434  c->c2.buf.len = 0; /* don't pass packet on */
435 }
context_2::max_send_size_local
int max_send_size_local
Definition: openvpn.h:313
buf_safe
static bool buf_safe(const struct buffer *buf, size_t len)
Definition: buffer.h:525
context_2::occ_mtu_load_n_tries
int occ_mtu_load_n_tries
Definition: openvpn.h:321
OCC_REQUEST
#define OCC_REQUEST
Definition: occ.h:36
M_INFO
#define M_INFO
Definition: errlevel.h:55
D_PACKET_CONTENT
#define D_PACKET_CONTENT
Definition: errlevel.h:168
mtu_load_test::op
int op
Definition: occ.h:74
forward.h
PACKAGE_NAME
#define PACKAGE_NAME
Definition: config.h:492
buffer::len
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
context_2::buf
struct buffer buf
Definition: openvpn.h:378
options_cmp_equal_safe
bool options_cmp_equal_safe(char *actual, const char *expected, size_t actual_n)
Definition: options.c:4612
TLS_MODE
#define TLS_MODE(c)
Definition: openvpn.h:539
context_2::max_recv_size_local
int max_recv_size_local
Definition: openvpn.h:311
frame_calculate_payload_size
size_t frame_calculate_payload_size(const struct frame *frame, const struct options *options, const struct key_type *kt)
Calculates the size of the payload according to tun-mtu and tap overhead.
Definition: mtu.c:142
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:209
context
Contains all state information for one tunnel.
Definition: openvpn.h:476
frame_calculate_payload_overhead
size_t frame_calculate_payload_overhead(size_t extra_tun, const struct options *options, const struct key_type *kt)
Calculates the size of the payload overhead according to tun-mtu and tap overhead.
Definition: mtu.c:101
get_random
long int get_random(void)
Definition: crypto.c:1611
mtu_load_test_sequence
static const struct mtu_load_test mtu_load_test_sequence[]
Definition: occ.c:60
options_warning_safe
void options_warning_safe(char *actual, const char *expected, size_t actual_n)
Definition: options.c:4635
dmsg
#define dmsg(flags,...)
Definition: error.h:148
options::ce
struct connection_entry ce
Definition: options.h:275
OCC_STRING_SIZE
#define OCC_STRING_SIZE
Definition: occ.h:30
context_2::buffers
struct context_buffers * buffers
Definition: openvpn.h:370
frame_calculate_protocol_header_size
size_t frame_calculate_protocol_header_size(const struct key_type *kt, const struct options *options, bool occ)
Calculates the size of the OpenVPN protocol header.
Definition: mtu.c:63
proto_is_dgram
static bool proto_is_dgram(int proto)
Return if the protocol is datagram (UDP)
Definition: socket.h:584
context_2::link_read_bytes
counter_type link_read_bytes
Definition: openvpn.h:269
context_2::occ_interval
struct event_timeout occ_interval
Definition: openvpn.h:304
context_2::occ_mtu_load_size
int occ_mtu_load_size
Definition: openvpn.h:318
check_send_occ_req_dowork
void check_send_occ_req_dowork(struct context *c)
Definition: occ.c:147
OCC_REPLY
#define OCC_REPLY
Definition: occ.h:37
context::c2
struct context_2 c2
Level 2 context.
Definition: openvpn.h:517
OCC_EXIT
#define OCC_EXIT
Definition: occ.h:66
ASSERT
#define ASSERT(x)
Definition: error.h:195
D_STREAM_ERRORS
#define D_STREAM_ERRORS
Definition: errlevel.h:63
mtu_load_test
Definition: occ.h:72
D_SHOW_OCC
#define D_SHOW_OCC
Definition: errlevel.h:151
buf_advance
static bool buf_advance(struct buffer *buf, int size)
Definition: buffer.h:623
buf_write_u16
static bool buf_write_u16(struct buffer *dest, uint16_t data)
Definition: buffer.h:703
encrypt_sign
void encrypt_sign(struct context *c, bool comp_frag)
Process a data channel packet that will be sent through a VPN tunnel.
Definition: forward.c:646
BLEN
#define BLEN(buf)
Definition: buffer.h:127
key_schedule::key_type
struct key_type key_type
Definition: openvpn.h:57
buf_write_u8
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition: buffer.h:697
frame::payload_size
int payload_size
the maximum size that a payload that our buffers can hold from either tun device or network link.
Definition: mtu.h:102
context_2::occ_n_tries
int occ_n_tries
Definition: openvpn.h:303
process_received_occ_msg
void process_received_occ_msg(struct context *c)
Definition: occ.c:363
context::options
struct options options
Options loaded from command line or configuration file.
Definition: openvpn.h:478
buf_read_u16
static int buf_read_u16(struct buffer *buf)
Definition: buffer.h:808
occ_magic
const uint8_t occ_magic[]
Definition: occ.c:55
context_2::max_send_size_remote
int max_send_size_remote
Definition: openvpn.h:314
OCC_MTU_LOAD
#define OCC_MTU_LOAD
Definition: occ.h:53
context_2::options_string_remote
char * options_string_remote
Definition: openvpn.h:300
key_type
Definition: crypto.h:139
buf_write
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:673
OCC_MTU_LOAD_REQUEST
#define OCC_MTU_LOAD_REQUEST
Definition: occ.h:52
context_buffers::aux_buf
struct buffer aux_buf
Definition: openvpn.h:97
context_2::max_recv_size_remote
int max_recv_size_remote
Definition: openvpn.h:312
frame::buf
struct frame::@6 buf
context_2::frame
struct frame frame
Definition: openvpn.h:251
syshead.h
BPTR
#define BPTR(buf)
Definition: buffer.h:124
check_send_occ_load_test_dowork
void check_send_occ_load_test_dowork(struct context *c)
Definition: occ.c:184
occ.h
context::sig
struct signal_info * sig
Internal error signaling object.
Definition: openvpn.h:503
OCC_MTU_REPLY
#define OCC_MTU_REPLY
Definition: occ.h:55
context_2::occ_mtu_load_test_interval
struct event_timeout occ_mtu_load_test_interval
Definition: openvpn.h:320
TUN_MTU_MIN
#define TUN_MTU_MIN
Definition: mtu.h:60
counter_format
#define counter_format
Definition: common.h:31
connection_entry::remote
const char * remote
Definition: options.h:105
context_1::ks
struct key_schedule ks
Definition: openvpn.h:162
min_int
static int min_int(int x, int y)
Definition: integer.h:89
config.h
connection_entry::fragment
int fragment
Definition: options.h:132
OCC_MTU_REQUEST
#define OCC_MTU_REQUEST
Definition: occ.h:54
connection_entry::proto
int proto
Definition: options.h:99
context_2::link_read_bytes_auth
counter_type link_read_bytes_auth
Definition: openvpn.h:271
buf_read_u8
static int buf_read_u8(struct buffer *buf)
Definition: buffer.h:795
context_2::options_string_local
char * options_string_local
Definition: openvpn.h:299
event_timeout_clear
static void event_timeout_clear(struct event_timeout *et)
Clears the timeout and reset all values to 0.
Definition: interval.h:155
options::occ
bool occ
Definition: options.h:427
check_send_occ_msg_dowork
void check_send_occ_msg_dowork(struct context *c)
Definition: occ.c:217
register_signal
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
Definition: sig.c:231
context_2::occ_op
int occ_op
Definition: openvpn.h:302
memdbg.h
options::mtu_test
bool mtu_test
Definition: options.h:319
OCC_N_TRIES
#define OCC_N_TRIES
Definition: occ.h:47
event_timeout_reset
static void event_timeout_reset(struct event_timeout *et)
Resets a timer.
Definition: interval.h:189
msg
#define msg(flags,...)
Definition: error.h:144
frame::headroom
int headroom
the headroom in the buffer, this is choosen to allow all potential header to be added before the pack...
Definition: mtu.h:108
context::c1
struct context_1 c1
Level 1 context.
Definition: openvpn.h:516
connection_established
static bool connection_established(struct context *c)
Definition: forward.h:417