Ticket #49: tlsfloat.2.patch
File tlsfloat.2.patch, 11.0 KB (added by , 10 years ago) |
---|
-
src/openvpn/crypto.c
From bab19ca1b1f1b89dca00ca18e258dbe1dacf4891 Mon Sep 17 00:00:00 2001 From: avalentin <avalentin@marcant.net> Date: Tue, 17 Dec 2013 21:51:25 +0000 Subject: [PATCH] Floating: Add support for floating in TLS mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for floating in tls mode using the HMAC of a packet. It costs a roundtrip through the client list. Because it is bases on the HMAC, it shoudl be secure. The HMAC calculation is very fast, (~700k/s), so this won't be a problem for medium size servers. URL: https://community.openvpn.net/openvpn/ticket/49 Signed-off-by: André Valentin <avalentin@marcant.net> --- src/openvpn/crypto.c | 55 ++++++++++++++++++++++++ src/openvpn/crypto.h | 4 ++ src/openvpn/mudp.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/mudp.h | 18 ++++++++ src/openvpn/options.c | 3 ++ src/openvpn/perf.h | 2 + src/openvpn/ssl.c | 28 +++++++++++++ src/openvpn/ssl.h | 6 +++ 8 files changed, 228 insertions(+) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index c4c356d..6446eee 100644
a b openvpn_decrypt (struct buffer *buf, struct buffer work, 389 389 } 390 390 391 391 /* 392 * This verifies if a packet and its HMAC fit to a crypto context. 393 * 394 * On success true is returned. 395 */ 396 bool 397 crypto_test_hmac (struct buffer *buf, 398 const struct crypto_options *opt) 399 { 400 struct gc_arena gc; 401 gc_init (&gc); 402 int offset = 1; 403 404 if (buf->len > 0 && opt->key_ctx_bi) 405 { 406 struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; 407 408 /* Verify the HMAC */ 409 if (ctx->hmac) 410 { 411 int hmac_len; 412 uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ 413 414 hmac_ctx_reset(ctx->hmac); 415 416 /* Assume the length of the input HMAC */ 417 hmac_len = hmac_ctx_size (ctx->hmac); 418 419 /* Authentication fails if insufficient data in packet for HMAC */ 420 if ((buf->len - offset) < hmac_len) 421 { 422 gc_free (&gc); 423 return false; 424 } 425 426 hmac_ctx_update (ctx->hmac, BPTR (buf) + offset + hmac_len, BLEN (buf) - offset - hmac_len); 427 hmac_ctx_final (ctx->hmac, local_hmac); 428 429 /* Compare locally computed HMAC with packet HMAC */ 430 if (memcmp (local_hmac, BPTR (buf) + offset, hmac_len)) 431 { 432 gc_free (&gc); 433 return false; 434 } 435 436 gc_free (&gc); 437 return true; 438 } 439 } 440 441 gc_free (&gc); 442 return false; 443 } 444 445 446 /* 392 447 * How many bytes will we add to frame buffer for a given 393 448 * set of crypto options? 394 449 */ -
src/openvpn/crypto.h
diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 3b4b88e..296519a 100644
a b bool openvpn_decrypt (struct buffer *buf, struct buffer work, 279 279 const struct crypto_options *opt, 280 280 const struct frame* frame); 281 281 282 283 bool crypto_test_hmac (struct buffer *buf, 284 const struct crypto_options *opt); 285 282 286 /** @} name Functions for performing security operations on data channel packets */ 283 287 284 288 void crypto_adjust_frame_parameters(struct frame *frame, -
src/openvpn/mudp.c
diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 3468dab..834d386 100644
a b multi_get_create_instance_udp (struct multi_context *m) 63 63 { 64 64 mi = (struct multi_instance *) he->value; 65 65 } 66 else if (multi_find_instance_udp (m, mi, real)) 67 { 68 /* found instance */ 69 msg (D_MULTI_LOW, "MULTI: Floated with HMAC authentication to a new client address: %s", 70 print_link_socket_actual (&m->top.c2.from, &gc)); 71 } 66 72 else 67 73 { 68 74 if (!m->top.c2.tls_auth_standalone … … multi_get_create_instance_udp (struct multi_context *m) 111 117 } 112 118 113 119 /* 120 * Find a client instance based on the HMAC, if auth is used. The function 121 * iterates over all peers to find a fitting instance. The found instance is 122 * updated with the current peer address. 123 * If the instance doesn't exist, return false. 124 */ 125 bool 126 multi_find_instance_udp (struct multi_context *m, struct multi_instance *mi, 127 struct mroute_addr real) 128 { 129 struct gc_arena gc = gc_new (); 130 struct hash *hash = m->hash; 131 struct hash_element *he; 132 const uint32_t hv = hash_value (hash, &real); 133 struct hash_bucket *bucket = hash_bucket (hash, hv); 134 struct hash_iterator hi; 135 struct mroute_addr real_old; 136 int op; 137 uint8_t c; 138 139 perf_push (PERF_MULTI_FIND_INSTANCE); 140 141 /* try to detect client floating */ 142 if (!m->top.options.ce.remote_float 143 || !m->top.options.authname_defined) 144 goto err; 145 146 /* minimum size 1 byte */ 147 if (m->top.c2.buf.len < 1) 148 goto err; 149 150 /* Only accept DATA_V1 opcode */ 151 c = *BPTR (&m->top.c2.buf); 152 op = c >> P_OPCODE_SHIFT; 153 if (op != P_DATA_V1) 154 goto err; 155 156 hash_iterator_init (hash, &hi); 157 while ((he = hash_iterator_next (&hi))) 158 { 159 mi = (struct multi_instance *) he->value; 160 161 /* verify if this instance allows hmac verification */ 162 if (!crypto_test_hmac (&m->top.c2.buf, &mi->context.c2.crypto_options)) 163 continue; 164 165 generate_prefix (mi); 166 msg (D_MULTI_MEDIUM, "MULTI: Detected floating by hmac test, new client address: %s", 167 print_link_socket_actual (&m->top.c2.from, &gc)); 168 169 /* update address */ 170 real_old = mi->real; 171 memcpy(&mi->real, &real, sizeof(real)); 172 173 mi->context.c2.from = m->top.c2.from; 174 mi->context.c2.to_link_addr = &mi->context.c2.from; 175 176 /* switch to new log prefix */ 177 generate_prefix (mi); 178 179 /* inherit buffers */ 180 mi->context.c2.buffers = m->top.c2.buffers; 181 182 /* inherit parent link_socket and link_socket_info */ 183 mi->context.c2.link_socket = m->top.c2.link_socket; 184 mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; 185 186 /* fix remote_addr in tls structure */ 187 tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from); 188 189 mi->did_open_context = true; 190 if (IS_SIG (&mi->context)) 191 goto errloop; 192 193 /* remove and readd this instance under the new address */ 194 hash_iterator_delete_element (&hi); 195 hash_add_fast (hash, bucket, &mi->real, hv, mi); 196 hash_remove (m->iter, &real_old); 197 hash_add (m->iter, &mi->real, mi, false); 198 #ifdef MANAGEMENT_DEF_AUTH 199 hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid); 200 hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false); 201 #endif 202 203 /* enforce update */ 204 mi->did_real_hash = true; 205 mi->did_iter = true; 206 #ifdef MANAGEMENT_DEF_AUTH 207 mi->did_cid_hash = true; 208 #endif 209 210 /* cleanup */ 211 hash_iterator_free (&hi); 212 perf_pop (); 213 gc_free (&gc); 214 return true; 215 } 216 217 errloop: 218 hash_iterator_free (&hi); 219 err: 220 perf_pop (); 221 gc_free (&gc); 222 return false; 223 } 224 225 /* 114 226 * Send a packet to TCP/UDP socket. 115 227 */ 116 228 static inline void -
src/openvpn/mudp.h
diff --git a/src/openvpn/mudp.h b/src/openvpn/mudp.h index 97f961b..759ea6d 100644
a b void tunnel_server_udp (struct context *top); 67 67 */ 68 68 struct multi_instance *multi_get_create_instance_udp (struct multi_context *m); 69 69 70 71 /**************************************************************************/ 72 /** 73 * Find a client instance based on the HMAC, if auth is used. 74 * @ingroup external_multiplexer 75 * 76 * Find a client instance based on the HMAC, if auth is used. The function 77 * iterates over all peers to find a fitting instance. The found instance is 78 * updated with the current peer address. 79 * 80 * @param m - The single multi_context structure. 81 * @param mi - The multi_instance structure. 82 * @param real - The mroute_addr structure. 83 * 84 * @return Boolen, true if peer found, false if not. 85 */ 86 bool multi_find_instance_udp (struct multi_context *m, struct multi_instance *mi, struct mroute_addr real); 87 70 88 #endif 71 89 #endif -
src/openvpn/options.c
diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 6d9c3b8..94ecd80 100644
a b static const char usage_message[] = 166 166 " Set n=\"infinite\" to retry indefinitely.\n" 167 167 "--float : Allow remote to change its IP address/port, such as through\n" 168 168 " DHCP (this is the default if --remote is not used).\n" 169 #ifdef ENABLE_CRYPTO 170 " In server mode a valid/default auth algo is needed.\n" 171 #endif 169 172 "--ipchange cmd : Run command cmd on remote ip address initial\n" 170 173 " setting or change -- execute as: cmd ip-address port#\n" 171 174 "--port port : TCP/UDP port # for both local and remote.\n" -
src/openvpn/perf.h
diff --git a/src/openvpn/perf.h b/src/openvpn/perf.h index c531d9c..e1121d2 100644
a b 57 57 #define PERF_PROC_OUT_TUN 18 58 58 #define PERF_PROC_OUT_TUN_MTCP 19 59 59 #define PERF_N 20 60 #define PERF_MULTI_FIND_INSTANCE 21 61 60 62 61 63 #ifdef ENABLE_PERFORMANCE_METRICS 62 64 -
src/openvpn/ssl.c
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index bd19d75..685a2b3 100644
a b tls_rec_payload (struct tls_multi *multi, 3448 3448 return ret; 3449 3449 } 3450 3450 3451 /* Update the remote_addr, needed if a client floats. */ 3452 void 3453 tls_update_remote_addr (struct tls_multi *multi, 3454 const struct link_socket_actual *from) 3455 { 3456 struct gc_arena gc = gc_new (); 3457 int i; 3458 3459 for (i = 0; i < KEY_SCAN_SIZE; ++i) 3460 { 3461 struct key_state *ks = multi->key_scan[i]; 3462 if (DECRYPT_KEY_ENABLED (multi, ks) 3463 && ks->authenticated 3464 && link_socket_actual_defined(&ks->remote_addr) 3465 ) 3466 { 3467 if (link_socket_actual_match (from, &ks->remote_addr)) 3468 continue; 3469 dmsg (D_TLS_KEYSELECT, 3470 "TLS: tls_update_remote_addr from IP=%s to IP=%s", 3471 print_link_socket_actual (&ks->remote_addr, &gc), 3472 print_link_socket_actual (from, &gc)); 3473 memcpy(&ks->remote_addr, from, sizeof(*from)); 3474 } 3475 } 3476 gc_free (&gc); 3477 } 3478 3451 3479 /* 3452 3480 * Dump a human-readable rendition of an openvpn packet 3453 3481 * into a garbage collectable string which is returned. -
src/openvpn/ssl.h
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index cd7cae2..c501b64 100644
a b bool tls_send_payload (struct tls_multi *multi, 431 431 bool tls_rec_payload (struct tls_multi *multi, 432 432 struct buffer *buf); 433 433 434 /* 435 * Update remote address of a tls_multi structure 436 */ 437 void tls_update_remote_addr (struct tls_multi *multi, 438 const struct link_socket_actual *from); 439 434 440 #ifdef MANAGEMENT_DEF_AUTH 435 441 static inline char * 436 442 tls_get_peer_info(const struct tls_multi *multi)