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-2022 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 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "occ.h"
33 #include "forward.h"
34 #include "memdbg.h"
35 
36 
37 /*
38  * This random string identifies an OpenVPN
39  * Configuration Control packet.
40  * It should be of sufficient length and randomness
41  * so as not to collide with other tunnel data.
42  *
43  * The OCC protocol is as follows:
44  *
45  * occ_magic -- (16 octets)
46  *
47  * type [OCC_REQUEST | OCC_REPLY] (1 octet)
48  * null terminated options string if OCC_REPLY (variable)
49  *
50  * When encryption is used, the OCC packet
51  * is encapsulated within the encrypted
52  * envelope.
53  *
54  * OCC_STRING_SIZE must be set to sizeof (occ_magic)
55  */
56 
57 const uint8_t occ_magic[] = {
58  0x28, 0x7f, 0x34, 0x6b, 0xd4, 0xef, 0x7a, 0x81,
59  0x2d, 0x56, 0xb8, 0xd3, 0xaf, 0xc5, 0x45, 0x9c
60 };
61 
62 static const struct mtu_load_test mtu_load_test_sequence[] = {
63 
64  {OCC_MTU_LOAD_REQUEST, -1000},
65  {OCC_MTU_LOAD, -1000},
66  {OCC_MTU_LOAD_REQUEST, -1000},
67  {OCC_MTU_LOAD, -1000},
68  {OCC_MTU_LOAD_REQUEST, -1000},
69  {OCC_MTU_LOAD, -1000},
70 
71  {OCC_MTU_LOAD_REQUEST, -750},
72  {OCC_MTU_LOAD, -750},
73  {OCC_MTU_LOAD_REQUEST, -750},
74  {OCC_MTU_LOAD, -750},
75  {OCC_MTU_LOAD_REQUEST, -750},
76  {OCC_MTU_LOAD, -750},
77 
78  {OCC_MTU_LOAD_REQUEST, -500},
79  {OCC_MTU_LOAD, -500},
80  {OCC_MTU_LOAD_REQUEST, -500},
81  {OCC_MTU_LOAD, -500},
82  {OCC_MTU_LOAD_REQUEST, -500},
83  {OCC_MTU_LOAD, -500},
84 
85  {OCC_MTU_LOAD_REQUEST, -400},
86  {OCC_MTU_LOAD, -400},
87  {OCC_MTU_LOAD_REQUEST, -400},
88  {OCC_MTU_LOAD, -400},
89  {OCC_MTU_LOAD_REQUEST, -400},
90  {OCC_MTU_LOAD, -400},
91 
92  {OCC_MTU_LOAD_REQUEST, -300},
93  {OCC_MTU_LOAD, -300},
94  {OCC_MTU_LOAD_REQUEST, -300},
95  {OCC_MTU_LOAD, -300},
96  {OCC_MTU_LOAD_REQUEST, -300},
97  {OCC_MTU_LOAD, -300},
98 
99  {OCC_MTU_LOAD_REQUEST, -200},
100  {OCC_MTU_LOAD, -200},
101  {OCC_MTU_LOAD_REQUEST, -200},
102  {OCC_MTU_LOAD, -200},
103  {OCC_MTU_LOAD_REQUEST, -200},
104  {OCC_MTU_LOAD, -200},
105 
106  {OCC_MTU_LOAD_REQUEST, -150},
107  {OCC_MTU_LOAD, -150},
108  {OCC_MTU_LOAD_REQUEST, -150},
109  {OCC_MTU_LOAD, -150},
110  {OCC_MTU_LOAD_REQUEST, -150},
111  {OCC_MTU_LOAD, -150},
112 
113  {OCC_MTU_LOAD_REQUEST, -100},
114  {OCC_MTU_LOAD, -100},
115  {OCC_MTU_LOAD_REQUEST, -100},
116  {OCC_MTU_LOAD, -100},
117  {OCC_MTU_LOAD_REQUEST, -100},
118  {OCC_MTU_LOAD, -100},
119 
120  {OCC_MTU_LOAD_REQUEST, -50},
121  {OCC_MTU_LOAD, -50},
122  {OCC_MTU_LOAD_REQUEST, -50},
123  {OCC_MTU_LOAD, -50},
124  {OCC_MTU_LOAD_REQUEST, -50},
125  {OCC_MTU_LOAD, -50},
126 
128  {OCC_MTU_LOAD, 0},
130  {OCC_MTU_LOAD, 0},
132  {OCC_MTU_LOAD, 0},
133 
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  {OCC_MTU_REQUEST, 0},
143  {OCC_MTU_REQUEST, 0},
144 
145  {-1, 0}
146 };
147 
148 void
150 {
151  if (++c->c2.occ_n_tries >= OCC_N_TRIES)
152  {
153  if (c->options.ce.remote)
154  {
155  /*
156  * No OCC_REPLY from peer after repeated attempts.
157  * Give up.
158  */
159  msg(D_SHOW_OCC,
160  "NOTE: failed to obtain options consistency info from peer -- "
161  "this could occur if the remote peer is running a version of "
163  " before 1.5-beta8 or if there is a network connectivity problem, and will not necessarily prevent "
165  " from running (" counter_format " bytes received from peer, " counter_format
166  " bytes authenticated data channel traffic) -- you can disable the options consistency "
167  "check with --disable-occ.",
168  c->c2.link_read_bytes,
170  }
172  }
173  else
174  {
175  c->c2.occ_op = OCC_REQUEST;
176 
177  /*
178  * If we don't hear back from peer, send another
179  * OCC_REQUEST in OCC_INTERVAL_SECONDS.
180  */
182  }
183 }
184 
185 void
187 {
188  if (connection_established(c))
189  {
190  const struct mtu_load_test *entry;
191 
192  if (!c->c2.occ_mtu_load_n_tries)
193  {
194  msg(M_INFO,
195  "NOTE: Beginning empirical MTU test -- results should be available in 3 to 4 minutes.");
196  }
197 
199  if (entry->op >= 0)
200  {
201  c->c2.occ_op = entry->op;
202  size_t payload_size = frame_calculate_payload_size(&c->c2.frame,
203  &c->options, &c->c1.ks.key_type);
204  size_t header_size = frame_calculate_protocol_header_size(&c->c1.ks.key_type, &c->options, false);
205 
206  c->c2.occ_mtu_load_size = payload_size + header_size;
207  }
208  else
209  {
210  msg(M_INFO,
211  "NOTE: failed to empirically measure MTU (requires " PACKAGE_NAME " 1.5 or higher at other end of connection).");
213  c->c2.occ_mtu_load_n_tries = 0;
214  }
215  }
216 }
217 
218 void
220 {
221  bool doit = false;
222 
223  c->c2.buf = c->c2.buffers->aux_buf;
224  ASSERT(buf_init(&c->c2.buf, c->c2.frame.buf.headroom));
227 
228  switch (c->c2.occ_op)
229  {
230  case OCC_REQUEST:
231  if (!buf_write_u8(&c->c2.buf, OCC_REQUEST))
232  {
233  break;
234  }
235  dmsg(D_PACKET_CONTENT, "SENT OCC_REQUEST");
236  doit = true;
237  break;
238 
239  case OCC_REPLY:
240  if (!c->c2.options_string_local)
241  {
242  break;
243  }
244  if (!buf_write_u8(&c->c2.buf, OCC_REPLY))
245  {
246  break;
247  }
248  if (!buf_write(&c->c2.buf, c->c2.options_string_local,
249  strlen(c->c2.options_string_local) + 1))
250  {
251  break;
252  }
253  dmsg(D_PACKET_CONTENT, "SENT OCC_REPLY");
254  doit = true;
255  break;
256 
257  case OCC_MTU_REQUEST:
258  if (!buf_write_u8(&c->c2.buf, OCC_MTU_REQUEST))
259  {
260  break;
261  }
262  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_REQUEST");
263  doit = true;
264  break;
265 
266  case OCC_MTU_REPLY:
267  if (!buf_write_u8(&c->c2.buf, OCC_MTU_REPLY))
268  {
269  break;
270  }
271  if (!buf_write_u16(&c->c2.buf, c->c2.max_recv_size_local))
272  {
273  break;
274  }
275  if (!buf_write_u16(&c->c2.buf, c->c2.max_send_size_local))
276  {
277  break;
278  }
279  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_REPLY");
280  doit = true;
281  break;
282 
285  {
286  break;
287  }
288  if (!buf_write_u16(&c->c2.buf, c->c2.occ_mtu_load_size))
289  {
290  break;
291  }
292  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_LOAD_REQUEST");
293  doit = true;
294  break;
295 
296  case OCC_MTU_LOAD:
297  {
298  int need_to_add;
299 
300  if (!buf_write_u8(&c->c2.buf, OCC_MTU_LOAD))
301  {
302  break;
303  }
304  size_t proto_hdr, payload_hdr;
305  const struct key_type *kt = &c->c1.ks.key_type;
306 
307  /* OCC message have comp/fragment headers but not ethernet headers */
308  payload_hdr = frame_calculate_payload_overhead(&c->c2.frame, &c->options,
309  kt, false);
310 
311  /* Since we do not know the payload size we just pass 0 as size here */
312  proto_hdr = frame_calculate_protocol_header_size(kt, &c->options, false);
313 
314  need_to_add = min_int(c->c2.occ_mtu_load_size, c->c2.frame.buf.payload_size)
316  - sizeof(uint8_t) /* occ opcode */
317  - payload_hdr
318  - proto_hdr;
319 
320  while (need_to_add > 0)
321  {
322  /*
323  * Fill the load test packet with pseudo-random bytes.
324  */
325  if (!buf_write_u8(&c->c2.buf, get_random() & 0xFF))
326  {
327  break;
328  }
329  --need_to_add;
330  }
331  dmsg(D_PACKET_CONTENT, "SENT OCC_MTU_LOAD min_int(%d,%d)-%d-%d-%d-%d) size=%d",
335  (int) sizeof(uint8_t),
336  (int) payload_hdr,
337  (int) proto_hdr,
338  BLEN(&c->c2.buf));
339  doit = true;
340  }
341  break;
342 
343  case OCC_EXIT:
344  if (!buf_write_u8(&c->c2.buf, OCC_EXIT))
345  {
346  break;
347  }
348  dmsg(D_PACKET_CONTENT, "SENT OCC_EXIT");
349  doit = true;
350  break;
351  }
352 
353  if (doit)
354  {
355  /*
356  * We will treat the packet like any other outgoing packet,
357  * compress, encrypt, sign, etc.
358  */
359  encrypt_sign(c, true);
360  }
361 
362  c->c2.occ_op = -1;
363 }
364 
365 void
367 {
369  switch (buf_read_u8(&c->c2.buf))
370  {
371  case OCC_REQUEST:
372  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_REQUEST");
373  c->c2.occ_op = OCC_REPLY;
374  break;
375 
376  case OCC_MTU_REQUEST:
377  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_REQUEST");
378  c->c2.occ_op = OCC_MTU_REPLY;
379  break;
380 
382  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_LOAD_REQUEST");
384  if (c->c2.occ_mtu_load_size >= 0)
385  {
386  c->c2.occ_op = OCC_MTU_LOAD;
387  }
388  break;
389 
390  case OCC_REPLY:
391  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_REPLY");
392  if (c->options.occ && !TLS_MODE(c) && c->c2.options_string_remote)
393  {
394  if (!options_cmp_equal_safe((char *) BPTR(&c->c2.buf),
396  c->c2.buf.len))
397  {
398  options_warning_safe((char *) BPTR(&c->c2.buf),
400  c->c2.buf.len);
401  }
402  }
404  break;
405 
406  case OCC_MTU_REPLY:
407  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_MTU_REPLY");
410  if (c->options.mtu_test
411  && c->c2.max_recv_size_remote > 0
412  && c->c2.max_send_size_remote > 0)
413  {
414  msg(M_INFO, "NOTE: Empirical MTU test completed [Tried,Actual] local->remote=[%d,%d] remote->local=[%d,%d]",
419  if (!c->options.ce.fragment
420  && (proto_is_dgram(c->options.ce.proto))
424  {
425  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.",
427  }
428  }
430  break;
431 
432  case OCC_EXIT:
433  dmsg(D_PACKET_CONTENT, "RECEIVED OCC_EXIT");
435  c->sig->signal_text = "remote-exit";
436  break;
437  }
438  c->c2.buf.len = 0; /* don't pass packet on */
439 }
context_2::max_send_size_local
int max_send_size_local
Definition: openvpn.h:311
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:319
signal_info::signal_received
volatile int signal_received
Definition: sig.h:45
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:165
mtu_load_test::op
int op
Definition: occ.h:74
forward.h
signal_info::signal_text
const char * signal_text
Definition: sig.h:47
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:376
options_cmp_equal_safe
bool options_cmp_equal_safe(char *actual, const char *expected, size_t actual_n)
Definition: options.c:4538
TLS_MODE
#define TLS_MODE(c)
Definition: openvpn.h:537
context_2::max_recv_size_local
int max_recv_size_local
Definition: openvpn.h:309
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:156
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:196
context
Contains all state information for one tunnel.
Definition: openvpn.h:474
get_random
long int get_random(void)
Definition: crypto.c:1634
config-msvc.h
mtu_load_test_sequence
static const struct mtu_load_test mtu_load_test_sequence[]
Definition: occ.c:62
frame::buf
struct frame::@5 buf
options_warning_safe
void options_warning_safe(char *actual, const char *expected, size_t actual_n)
Definition: options.c:4561
dmsg
#define dmsg(flags,...)
Definition: error.h:154
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:368
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:73
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:302
context_2::occ_mtu_load_size
int occ_mtu_load_size
Definition: openvpn.h:316
check_send_occ_req_dowork
void check_send_occ_req_dowork(struct context *c)
Definition: occ.c:149
OCC_REPLY
#define OCC_REPLY
Definition: occ.h:37
context::c2
struct context_2 c2
Level 2 context.
Definition: openvpn.h:515
OCC_EXIT
#define OCC_EXIT
Definition: occ.h:66
ASSERT
#define ASSERT(x)
Definition: error.h:201
mtu_load_test
Definition: occ.h:72
D_SHOW_OCC
#define D_SHOW_OCC
Definition: errlevel.h:97
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:551
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:301
process_received_occ_msg
void process_received_occ_msg(struct context *c)
Definition: occ.c:366
context::options
struct options options
Options loaded from command line or configuration file.
Definition: openvpn.h:476
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:57
context_2::max_send_size_remote
int max_send_size_remote
Definition: openvpn.h:312
OCC_MTU_LOAD
#define OCC_MTU_LOAD
Definition: occ.h:53
context_2::options_string_remote
char * options_string_remote
Definition: openvpn.h:298
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:94
context_2::max_recv_size_remote
int max_recv_size_remote
Definition: openvpn.h:310
context_2::frame
struct frame frame
Definition: openvpn.h:248
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:186
occ.h
SIGUSR1
#define SIGUSR1
Definition: config-msvc.h:80
context::sig
struct signal_info * sig
Internal error signaling object.
Definition: openvpn.h:501
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:318
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:107
context_1::ks
struct key_schedule ks
Definition: openvpn.h:159
min_int
static int min_int(int x, int y)
Definition: integer.h:82
config.h
connection_entry::fragment
int fragment
Definition: options.h:134
frame_calculate_payload_overhead
size_t frame_calculate_payload_overhead(const struct frame *frame, const struct options *options, const struct key_type *kt, bool extra_tun)
Calculates the size of the payload overhead according to tun-mtu and tap overhead.
Definition: mtu.c:111
OCC_MTU_REQUEST
#define OCC_MTU_REQUEST
Definition: occ.h:54
connection_entry::proto
int proto
Definition: options.h:101
context_2::link_read_bytes_auth
counter_type link_read_bytes_auth
Definition: openvpn.h:270
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:297
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:428
check_send_occ_msg_dowork
void check_send_occ_msg_dowork(struct context *c)
Definition: occ.c:219
context_2::occ_op
int occ_op
Definition: openvpn.h:300
memdbg.h
options::mtu_test
bool mtu_test
Definition: options.h:317
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:150
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:514
connection_established
static bool connection_established(struct context *c)
Definition: forward.h:415