2 * routines for openvpn packet dissasembly
3 * - http://www.openvpn.net
4 * - http://fengnet.com/book/vpns%20illustrated%20tunnels%20%20vpnsand%20ipsec/ch08lev1sec5.html
6 * Created as part of a semester project at the University of Applied Sciences Hagenberg
7 * (http://www.fh-ooe.at/en/hagenberg-campus/)
10 * Hofer Manuel (manuel@mnlhfr.at)
16 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <epan/packet.h>
22 #include <epan/prefs.h>
23 #include <epan/reassemble.h>
24 #include <epan/conversation.h>
25 #include "packet-tcp.h"
27 void proto_register_openvpn(void);
28 void proto_reg_handoff_openvpn(void);
30 #define PFNAME "openvpn"
31 #define PNAME "OpenVPN Protocol"
32 #define PSNAME "OpenVPN"
34 #define OPENVPN_PORT 1194
36 /* packet opcode and key-id are combined in one byte */
37 #define P_OPCODE_MASK 0xF8 /* packet opcode (high 5 bits) */
38 #define P_KEY_ID_MASK 0x07 /* key-id (low 3 bits) */
39 #define HMAC_KEY_LENGTH_MAX 64 /* 512 Bit HMAC is maximum */
42 #define P_CONTROL_HARD_RESET_CLIENT_V1 1
43 #define P_CONTROL_HARD_RESET_SERVER_V1 2
44 #define P_CONTROL_SOFT_RESET_V1 3
45 #define P_CONTROL_V1 4
48 #define P_CONTROL_HARD_RESET_CLIENT_V2 7
49 #define P_CONTROL_HARD_RESET_SERVER_V2 8
51 #define P_CONTROL_HARD_RESET_CLIENT_V3 10
52 #define P_CONTROL_WKC_V1 11
54 static int ett_openvpn
;
55 static int ett_openvpn_data
;
56 static int ett_openvpn_packetarray
;
57 static int ett_openvpn_type
;
58 static int ett_openvpn_wkc
;
59 static int hf_openvpn_data
;
60 static int hf_openvpn_wkc_data
;
61 static int hf_openvpn_wkc_length
;
62 static int hf_openvpn_fragment_bytes
;
63 static int hf_openvpn_hmac
;
64 static int hf_openvpn_keyid
;
65 static int hf_openvpn_mpid
;
66 static int hf_openvpn_mpid_arrayelement
;
67 static int hf_openvpn_mpid_arraylength
;
68 static int hf_openvpn_net_time
;
69 static int hf_openvpn_opcode
;
70 static int hf_openvpn_pdu_type
;
71 static int hf_openvpn_pid
;
72 static int hf_openvpn_plen
;
73 static int hf_openvpn_rsessionid
;
74 static int hf_openvpn_sessionid
;
75 static int hf_openvpn_peerid
;
76 static int proto_openvpn
;
78 static dissector_handle_t openvpn_udp_handle
;
79 static dissector_handle_t openvpn_tcp_handle
;
81 static dissector_handle_t tls_handle
;
84 static bool pref_long_format
= true;
85 static bool pref_tls_auth
;
86 static bool pref_tls_auth_override
;
87 static bool pref_tls_crypt_override
;
88 static unsigned tls_auth_hmac_size
= 20; /* Default SHA-1 160 Bits */
90 static const value_string openvpn_message_types
[] =
92 { P_CONTROL_HARD_RESET_CLIENT_V1
, "P_CONTROL_HARD_RESET_CLIENT_V1" },
93 { P_CONTROL_HARD_RESET_SERVER_V1
, "P_CONTROL_HARD_RESET_SERVER_V1" },
94 { P_CONTROL_SOFT_RESET_V1
, "P_CONTROL_SOFT_RESET_V1" },
95 { P_CONTROL_V1
, "P_CONTROL_V1" },
96 { P_ACK_V1
, "P_ACK_V1" },
97 { P_DATA_V1
, "P_DATA_V1" },
98 { P_CONTROL_HARD_RESET_CLIENT_V2
, "P_CONTROL_HARD_RESET_CLIENT_V2" },
99 { P_CONTROL_HARD_RESET_SERVER_V2
, "P_CONTROL_HARD_RESET_SERVER_V2" },
100 { P_DATA_V2
, "P_DATA_V2" },
101 { P_CONTROL_HARD_RESET_CLIENT_V3
, "P_CONTROL_HARD_RESET_CLIENT_V3" },
102 { P_CONTROL_WKC_V1
, "P_CONTROL_WKC_V1" },
106 /* everything used during the reassembly process */
107 static reassembly_table msg_reassembly_table
;
109 static int ett_openvpn_fragment
;
110 static int ett_openvpn_fragments
;
111 static int hf_openvpn_fragment
;
112 static int hf_openvpn_fragment_count
;
113 static int hf_openvpn_fragment_error
;
114 static int hf_openvpn_fragment_multiple_tails
;
115 static int hf_openvpn_fragment_overlap
;
116 static int hf_openvpn_fragment_overlap_conflicts
;
117 static int hf_openvpn_fragment_too_long_fragment
;
118 static int hf_openvpn_fragments
;
119 static int hf_openvpn_reassembled_in
;
120 static int hf_openvpn_reassembled_length
;
122 static const fragment_items openvpn_frag_items
= {
123 /* Fragment subtrees */
124 &ett_openvpn_fragment
,
125 &ett_openvpn_fragments
,
126 /* Fragment fields */
127 &hf_openvpn_fragments
,
128 &hf_openvpn_fragment
,
129 &hf_openvpn_fragment_overlap
,
130 &hf_openvpn_fragment_overlap_conflicts
,
131 &hf_openvpn_fragment_multiple_tails
,
132 &hf_openvpn_fragment_too_long_fragment
,
133 &hf_openvpn_fragment_error
,
134 &hf_openvpn_fragment_count
,
135 /* Reassembled in field */
136 &hf_openvpn_reassembled_in
,
137 /* Reassembled length field */
138 &hf_openvpn_reassembled_length
,
139 /* Reassembled data field */
145 /* we check the leading 4 byte of a suspected hmac for 0x00 bytes,
146 if more than 1 byte out of the 4 provided contains 0x00, the
147 hmac is considered not valid, which suggests that no tls auth is used.
148 unfortunately there is no other way to detect tls auth on the fly */
150 check_for_valid_hmac(uint32_t hmac
)
153 if ((hmac
& 0x000000FF) == 0x00000000) {
156 if ((hmac
& 0x0000FF00) == 0x00000000) {
159 if ((hmac
& 0x00FF0000) == 0x00000000) {
162 if ((hmac
& 0xFF000000) == 0x00000000) {
173 dissect_openvpn_msg_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*openvpn_tree
, proto_tree
*parent_tree
, int offset
)
176 bool tls_crypt
= false;
177 unsigned openvpn_keyid
;
178 unsigned openvpn_opcode
;
179 uint32_t msg_sessionid
= -1;
180 uint8_t openvpn_predict_tlsauth_arraylength
;
182 proto_tree
*packetarray_tree
, *type_tree
;
183 uint32_t msg_length_remaining
;
186 /* Clear out stuff in the info column */
187 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PSNAME
);
188 col_clear(pinfo
->cinfo
,COL_INFO
);
190 /* read opcode and write to info column */
191 openvpn_opcode
= tvb_get_bits8(tvb
, offset
*8, 5);
192 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "MessageType: %s",
193 val_to_str_const(openvpn_opcode
, openvpn_message_types
, "Unknown Messagetype"));
196 openvpn_keyid
= tvb_get_bits8(tvb
, offset
*8 + 5, 3);
197 proto_item_append_text(parent_tree
, ", Opcode: %s, Key ID: %d",
198 val_to_str(openvpn_opcode
, openvpn_message_types
, "Unknown (0x%02x)"),
201 ti2
= proto_tree_add_item(openvpn_tree
, hf_openvpn_pdu_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
202 proto_item_append_text(ti2
, " [opcode/key_id]");
204 type_tree
= proto_item_add_subtree(ti2
, ett_openvpn_type
);
205 proto_tree_add_item(type_tree
, hf_openvpn_opcode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
206 proto_tree_add_item(type_tree
, hf_openvpn_keyid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
209 if (openvpn_opcode
== P_DATA_V2
) {
210 proto_tree_add_item(openvpn_tree
, hf_openvpn_peerid
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
212 } else if (openvpn_opcode
!= P_DATA_V1
) {
213 /* if we have a P_CONTROL or P_ACK packet */
216 msg_sessionid
= tvb_get_bits32(tvb
, offset
*8+32, 32, ENC_BIG_ENDIAN
);
217 proto_tree_add_item(openvpn_tree
, hf_openvpn_sessionid
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
220 /* tls-auth detection (this can be overridden by preferences */
221 openvpn_predict_tlsauth_arraylength
= tvb_get_uint8(tvb
, offset
);
223 /* if the first 4 bytes that would, if tls-auth is used, contain part of the hmac,
224 lack entropy, we assume no tls-auth is used */
225 if (pref_tls_auth_override
== false) {
226 if ((openvpn_opcode
!= P_DATA_V1
)
227 && (openvpn_predict_tlsauth_arraylength
> 0)
228 && check_for_valid_hmac(tvb_get_ntohl(tvb
, offset
))) {
234 tls_auth
= pref_tls_auth
;
237 if (openvpn_opcode
== P_CONTROL_HARD_RESET_CLIENT_V3
|| openvpn_opcode
== P_CONTROL_WKC_V1
|| pref_tls_crypt_override
== true) {
238 /* these opcodes are always tls-crypt*/
243 if (tls_auth
== true) {
244 proto_tree_add_item(openvpn_tree
, hf_openvpn_hmac
, tvb
, offset
, tls_auth_hmac_size
, ENC_NA
);
245 offset
+= tls_auth_hmac_size
;
248 if (tls_auth
== true || tls_crypt
== true) {
249 if (tvb_reported_length_remaining(tvb
, offset
) >= 8) {
250 proto_tree_add_item(openvpn_tree
, hf_openvpn_pid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
253 if (pref_long_format
|| tls_crypt
== true) {
254 proto_tree_add_item(openvpn_tree
, hf_openvpn_net_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
258 if (tls_crypt
== true) {
259 /* tls-crypt uses HMAC-SHA256 */
260 proto_tree_add_item(openvpn_tree
, hf_openvpn_hmac
, tvb
, offset
, 32, ENC_NA
);
265 if (tvb_reported_length_remaining(tvb
, offset
) >= 1 && tls_crypt
== false) {
266 /* read P_ACK packet-id array length */
267 int pid_arraylength
= tvb_get_uint8(tvb
, offset
);
269 proto_tree_add_item(openvpn_tree
, hf_openvpn_mpid_arraylength
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
272 if (pid_arraylength
> 0) {
274 packetarray_tree
= proto_tree_add_subtree(openvpn_tree
, tvb
, offset
, 0, ett_openvpn_packetarray
, NULL
, "Packet-ID Array");
275 for (i
= 0; i
< pid_arraylength
; i
++) {
276 proto_tree_add_item(packetarray_tree
, hf_openvpn_mpid_arrayelement
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
280 if (tvb_reported_length_remaining(tvb
, offset
) >= 8) {
281 proto_tree_add_item(openvpn_tree
, hf_openvpn_rsessionid
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
287 /* if we have a P_CONTROL packet */
288 if (openvpn_opcode
!= P_ACK_V1
&& tls_crypt
== false) {
289 /* read Message Packet-ID */
290 if (tvb_reported_length_remaining(tvb
, offset
) >= 4) {
291 proto_tree_add_item(openvpn_tree
, hf_openvpn_mpid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
297 /* if we have more data left, determine what to do */
298 msg_length_remaining
= tvb_reported_length_remaining(tvb
, offset
);
300 if (msg_length_remaining
== 0) {
301 return tvb_captured_length(tvb
);
304 int data_len
= msg_length_remaining
;
306 if ((openvpn_opcode
== P_CONTROL_HARD_RESET_CLIENT_V3
|| openvpn_opcode
== P_CONTROL_WKC_V1
)
307 && msg_length_remaining
>= 2) {
309 wkc_len
= tvb_get_ntohs(tvb
, tvb_reported_length(tvb
) - 2);
310 data_len
= msg_length_remaining
- wkc_len
;
313 if (openvpn_opcode
!= P_CONTROL_V1
) {
314 proto_tree
*data_tree
;
315 data_tree
= proto_tree_add_subtree_format(openvpn_tree
, tvb
, offset
, data_len
,
316 ett_openvpn_data
, NULL
, "Data (%d bytes)",
319 proto_tree_add_item(data_tree
, hf_openvpn_data
, tvb
, offset
, data_len
, ENC_NA
);
323 proto_tree
*wkc_tree
;
324 wkc_offset
= tvb_reported_length(tvb
) - wkc_len
;
326 wkc_tree
= proto_tree_add_subtree_format(openvpn_tree
, tvb
, offset
, data_len
,
327 ett_openvpn_wkc
, NULL
, "Wrapped client key (%d bytes)",
328 tvb_captured_length_remaining(tvb
, wkc_offset
));
330 proto_tree_add_item(wkc_tree
, hf_openvpn_wkc_data
, tvb
, wkc_offset
, wkc_len
, ENC_NA
);
331 proto_tree_add_item(wkc_tree
, hf_openvpn_wkc_length
, tvb
, tvb_reported_length(tvb
) - 2, 2, ENC_BIG_ENDIAN
);
334 return tvb_captured_length(tvb
);
337 /* Control message, possibly fragmented, carrying TLS. Try to reassemble. */
339 streaming_reassembly_info_t
*streaming_reassembly_info
= NULL
;
341 conversation_t
*conv
= find_or_create_conversation_by_id(pinfo
, CONVERSATION_OPENVPN
, msg_sessionid
);
342 streaming_reassembly_info
= conversation_get_proto_data(conv
, proto_openvpn
);
343 if (!streaming_reassembly_info
) {
344 streaming_reassembly_info
= streaming_reassembly_info_new();
345 conversation_add_proto_data(conv
, proto_openvpn
, streaming_reassembly_info
);
348 reassemble_streaming_data_and_call_subdissector(tvb
, pinfo
, offset
,
349 msg_length_remaining
, openvpn_tree
, parent_tree
, msg_reassembly_table
,
350 streaming_reassembly_info
, get_virtual_frame_num64(tvb
, pinfo
, offset
),
351 tls_handle
, parent_tree
, NULL
/* should it be tcpinfo if we have it? */, "OpenVPN Message",
352 &openvpn_frag_items
, hf_openvpn_fragment_bytes
);
354 return tvb_captured_length(tvb
);
358 get_msg_length(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
360 return (unsigned)tvb_get_ntohs(tvb
, offset
) + 2; /* length field is at offset 0,
361 +2 to account for the length field itself */
365 dissect_openvpn_msg_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
368 proto_tree
*openvpn_tree
;
370 ti
= proto_tree_add_item(tree
, proto_openvpn
, tvb
, 0, -1, ENC_NA
);
371 openvpn_tree
= proto_item_add_subtree(ti
, ett_openvpn
);
373 proto_tree_add_item(openvpn_tree
, hf_openvpn_plen
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
375 return dissect_openvpn_msg_common(tvb
, pinfo
, openvpn_tree
, tree
, 2);
379 dissect_openvpn_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
381 tcp_dissect_pdus( tvb
, pinfo
, tree
,
382 true, /* should data be reassembled? */
383 2, /* how much bytes do we need for get_msg_length to be successful,
384 since the length is the first thing in an openvpn packet we choose 2 */
385 get_msg_length
, /* fptr for function to get the packetlength of current frame */
386 dissect_openvpn_msg_tcp
, data
);
387 return tvb_captured_length(tvb
);
391 dissect_openvpn_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
394 proto_tree
*openvpn_tree
;
396 ti
= proto_tree_add_item(tree
, proto_openvpn
, tvb
, 0, -1, ENC_NA
);
397 openvpn_tree
= proto_item_add_subtree(ti
, ett_openvpn
);
399 return dissect_openvpn_msg_common(tvb
, pinfo
, openvpn_tree
, tree
, 0);
403 proto_register_openvpn(void)
405 static hf_register_info hf
[] = {
407 { "Packet Length", "openvpn.plen",
412 { &hf_openvpn_pdu_type
,
413 { "Type", "openvpn.type",
418 { &hf_openvpn_opcode
,
419 { "Opcode", "openvpn.opcode",
421 VALS(openvpn_message_types
), P_OPCODE_MASK
,
425 { "Key ID", "openvpn.keyid",
430 { &hf_openvpn_peerid
,
431 { "Peer ID", "openvpn.peerid",
436 { &hf_openvpn_sessionid
,
437 { "Session ID", "openvpn.sessionid",
443 { "HMAC", "openvpn.hmac",
449 { "Replay-Packet-ID", "openvpn.pid",
454 { &hf_openvpn_net_time
,
455 { "Net Time", "openvpn.net_time",
456 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
460 { &hf_openvpn_rsessionid
,
461 { "Remote Session ID", "openvpn.rsessionid",
467 { "Message Packet-ID", "openvpn.mpid",
472 { &hf_openvpn_mpid_arraylength
,
473 { "Message Packet-ID Array Length", "openvpn.mpidarraylength",
478 { &hf_openvpn_mpid_arrayelement
,
479 { "Message Packet-ID Array Element", "openvpn.mpidarrayelement",
485 { "Data", "openvpn.data",
490 { &hf_openvpn_wkc_data
,
491 { "Wrapped client key", "openvpn.wkc",
496 { &hf_openvpn_wkc_length
,
497 { "Wrapped client key length", "openvpn.wkc_len",
502 { &hf_openvpn_fragment_bytes
,
503 { "Fragment bytes", "openvpn.fragment_bytes",
508 { &hf_openvpn_fragments
,
509 { "Message fragments", "openvpn.fragments",
514 { &hf_openvpn_fragment
,
515 { "Message fragment", "openvpn.fragment",
516 FT_FRAMENUM
, BASE_NONE
,
520 { &hf_openvpn_fragment_overlap
,
521 { "Message fragment overlap", "openvpn.fragment.overlap",
522 FT_BOOLEAN
, BASE_NONE
,
526 { &hf_openvpn_fragment_overlap_conflicts
,
527 { "Message fragment overlapping with conflicting data", "openvpn.fragment.overlap.conflicts",
528 FT_BOOLEAN
, BASE_NONE
,
532 { &hf_openvpn_fragment_multiple_tails
,
533 { "Message has multiple tail fragments", "openvpn.fragment.multiple_tails",
534 FT_BOOLEAN
, BASE_NONE
,
538 { &hf_openvpn_fragment_too_long_fragment
,
539 { "Message fragment too long", "openvpn.fragment.too_long_fragment",
540 FT_BOOLEAN
, BASE_NONE
,
544 { &hf_openvpn_fragment_error
,
545 { "Message defragmentation error", "openvpn.fragment.error",
546 FT_FRAMENUM
, BASE_NONE
,
550 { &hf_openvpn_fragment_count
,
551 { "Message fragment count", "openvpn.fragment.count",
556 { &hf_openvpn_reassembled_in
,
557 { "Reassembled message in frame", "openvpn.reassembled.in",
558 FT_FRAMENUM
, BASE_NONE
,
562 { &hf_openvpn_reassembled_length
,
563 {"Reassembled message length", "openvpn.reassembled.length",
570 /* Setup protocol subtree array */
571 static int *ett
[] = {
576 &ett_openvpn_packetarray
,
577 &ett_openvpn_fragment
,
578 &ett_openvpn_fragments
580 module_t
*openvpn_module
;
582 proto_openvpn
= proto_register_protocol (
584 PSNAME
, /* short name */
588 proto_register_field_array(proto_openvpn
, hf
, array_length(hf
));
589 proto_register_subtree_array(ett
, array_length(ett
));
591 openvpn_udp_handle
= register_dissector("openvpn.udp", dissect_openvpn_udp
, proto_openvpn
);
592 openvpn_tcp_handle
= register_dissector("openvpn.tcp", dissect_openvpn_tcp
, proto_openvpn
);
594 reassembly_table_register(&msg_reassembly_table
,
595 &addresses_reassembly_table_functions
);
597 openvpn_module
= prefs_register_protocol(proto_openvpn
, NULL
);
599 prefs_register_bool_preference(openvpn_module
,
600 "tls_auth_detection_override",
601 "override tls-auth detection",
602 "If tls-auth detection fails, you can choose to override detection and set tls-auth yourself",
603 &pref_tls_auth_override
);
605 prefs_register_bool_preference(openvpn_module
,
608 "Assume the connection uses tls-crypt",
609 &pref_tls_crypt_override
);
610 prefs_register_bool_preference(openvpn_module
,
613 "If the parameter --tls-auth is used, the following preferences must also be defined.",
615 prefs_register_uint_preference(openvpn_module
,
616 "tls_auth_hmac_size",
617 "size of the HMAC header in bytes",
618 "If the parameter --tls-auth is used, a HMAC header is being inserted.\n"
619 "The default HMAC algorithm is SHA-1 which generates a 160 bit HMAC,"
620 " therefore 20 bytes should be ok.\n"
621 "The value must be between 20 (160 bits) and 64 (512 bits).",
622 10, &tls_auth_hmac_size
);
624 prefs_register_bool_preference(openvpn_module
,
626 "packet-id for replay protection includes optional time_t timestamp?",
627 "If the parameter --tls-auth is used, an additional packet-id for replay protection"
628 " is inserted after the HMAC signature."
629 " This field can either be 4 bytes or 8 bytes including an optional time_t timestamp long.\n"
630 " This option is only evaluated if tls_auth_hmac_size > 0.\n"
631 " The default value is true.",
636 proto_reg_handoff_openvpn(void)
638 tls_handle
= find_dissector_add_dependency("tls", proto_openvpn
);
639 dissector_add_uint_with_preference("tcp.port", OPENVPN_PORT
, openvpn_tcp_handle
);
640 dissector_add_uint_with_preference("udp.port", OPENVPN_PORT
, openvpn_udp_handle
);
644 * Editor modelines - https://www.wireshark.org/tools/modelines.html
649 * indent-tabs-mode: nil
652 * vi: set shiftwidth=2 tabstop=8 expandtab:
653 * :indentSize=2:tabSize=8:noTabs=true