📄 openvpn.c
字号:
* Make space for a uint32 to be removed from incoming TUN packets * and added to outgoing TUN packets. */ if (options->tun_af_inet) tun_adjust_frame_parameters (&frame, sizeof (uint32_t));#endif /* * Fill in the blanks in the frame parameters structure, * make sure values are rational, etc. */ frame_finalize (&frame, options); max_rw_size_udp = MAX_RW_SIZE_UDP (&frame); print_frame_parms (D_SHOW_PARMS, &frame, "Data Channel MTU parms");#if defined(USE_CRYPTO) && defined(USE_SSL) if (tls_multi) { int size; tls_multi_init_finalize (tls_multi, &frame); size = MAX_RW_SIZE_UDP (&tls_multi->opt.frame); if (size > max_rw_size_udp) max_rw_size_udp = size; print_frame_parms (D_SHOW_PARMS, &tls_multi->opt.frame, "Control Channel MTU parms"); }#endif /* * Now that we know all frame parameters, initialize * our buffers. */ read_udp_buf = alloc_buf (BUF_SIZE (&frame)); read_tun_buf = alloc_buf (BUF_SIZE (&frame));#ifdef USE_CRYPTO encrypt_buf = alloc_buf (BUF_SIZE (&frame)); decrypt_buf = alloc_buf (BUF_SIZE (&frame));#endif#ifdef USE_LZO if (options->comp_lzo) { lzo_compress_buf = alloc_buf (BUF_SIZE (&frame)); lzo_decompress_buf = alloc_buf (BUF_SIZE (&frame)); }#endif if (!tuntap_defined (tuntap)) { /* do ifconfig */ if (ifconfig_order() == IFCONFIG_BEFORE_TUN_OPEN) do_ifconfig (options->dev, options->dev_type, options->ifconfig_local, options->ifconfig_remote, MAX_RW_SIZE_TUN (&frame)); /* open the tun device */ open_tun (options->dev, options->dev_type, options->dev_node, options->tun_ipv6, tuntap); /* do ifconfig */ if (ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN) do_ifconfig (tuntap->actual, options->dev_type, options->ifconfig_local, options->ifconfig_remote, MAX_RW_SIZE_TUN (&frame)); /* run the up script */ run_script (options->up_script, tuntap->actual, MAX_RW_SIZE_TUN (&frame), max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote); } else { msg (M_INFO, "Preserving previous tun/tap instance: %s", tuntap->actual); } /* initialize traffic shaper */ if (options->shaper) shaper_init (&shaper, options->shaper); /* drop privileges if requested */ if (first_time) { set_group (options->groupname); set_user (options->username); } /* catch signals */ signal (SIGINT, signal_handler); signal (SIGTERM, signal_handler); signal (SIGHUP, signal_handler); signal (SIGUSR1, signal_handler); signal (SIGUSR2, signal_handler); /* start the TLS thread */#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD) if (tls_multi) tls_thread_socket = tls_thread_create (tls_multi, &udp_socket, options->nice_work, options->mlock);#endif /* change scheduling priority if requested */ if (first_time) set_nice (options->nice); /* * MAIN EVENT LOOP * * Pipe UDP -> tun and tun -> UDP using nonblocked i/o. * * If tls_multi is defined, multiplex a TLS * control channel over the UDP connection which * will be used for secure key exchange with our peer. * */ /* calculate max file handle + 1 for select */ fm = udp_socket.sd; if (tuntap->fd > fm) fm = tuntap->fd; current = time (NULL); /* initialize inactivity timeout */ if (options->inactivity_timeout) event_timeout_init (&inactivity_interval, current, options->inactivity_timeout); /* initialize pings */ if (options->ping_send_timeout) event_timeout_init (&ping_send_interval, 0, options->ping_send_timeout); if (options->ping_rec_timeout) event_timeout_init (&ping_rec_interval, current, options->ping_rec_timeout);#if defined(USE_CRYPTO) && defined(USE_SSL)#ifdef USE_PTHREAD if (tls_multi && tls_thread_socket > fm) fm = tls_thread_socket;#else /* initialize tmp_int optimization that limits the number of times we call tls_multi_process in the main event loop */ CLEAR (tmp_int); interval_trigger (&tmp_int, current);#endif#endif /* select() needs this */ ++fm; /* this flag is true for buffers coming from the TLS background thread */ free_to_udp = false; while (true) { int stat = 0; struct timeval *tv = NULL; struct timeval timeval; /* initialize select() timeout */ timeval.tv_sec = 0; timeval.tv_usec = 0;#if defined(USE_CRYPTO) && defined(USE_SSL) && !defined(USE_PTHREAD) /* * In TLS mode, let TLS level respond to any control-channel packets which were * received, or prepare any packets for transmission. * * tmp_int is purely an optimization that allows us to call tls_multi_process * less frequently when there's not much traffic on the control-channel. * */ if (tls_multi) { time_t t = 0; if (interval_test (&tmp_int, current)) { if (tls_multi_process (tls_multi, &to_udp, &to_udp_addr, &udp_socket, &t, current)) interval_trigger(&tmp_int, current); } interval_set_timeout (&tmp_int, current, &t); tv = &timeval; timeval.tv_sec = t; timeval.tv_usec = 0; free_to_udp = false; }#endif current = time (NULL); /* * Should we exit due to inactivity timeout? */ if (options->inactivity_timeout) { if (event_timeout_trigger (&inactivity_interval, current)) { msg (M_INFO, "Inactivity timeout (--inactive), exiting"); signal_received = 0; break; } event_timeout_wakeup (&inactivity_interval, current, &timeval); tv = &timeval; } /* * Should we exit or restart due to ping (or other authenticated packet) * not received in n seconds? */ if (options->ping_rec_timeout && (!options->ping_timer_remote || addr_defined (&udp_socket_addr->actual))) { if (event_timeout_trigger (&ping_rec_interval, current)) { switch (options->ping_rec_timeout_action) { case PING_EXIT: msg (M_INFO, "Inactivity timeout (--ping-exit), exiting"); signal_received = 0; break; case PING_RESTART: msg (M_INFO, "Inactivity timeout (--ping-restart), restarting"); signal_received = SIGUSR1; break; default: ASSERT (0); } break; } event_timeout_wakeup (&ping_rec_interval, current, &timeval); tv = &timeval; } /* * Should we ping the remote? */ if (options->ping_send_timeout) { if (!to_udp.len) { if (event_timeout_trigger (&ping_send_interval, current)) { buf = read_tun_buf; ASSERT (buf_init (&buf, EXTRA_FRAME (&frame))); ASSERT (buf_safe (&buf, MAX_RW_SIZE_TUN (&frame))); ASSERT (buf_write (&buf, ping_string, sizeof (ping_string))); /* * We will treat the ping like any other outgoing packet, * encrypt, authenticate, etc. */#ifdef USE_LZO if (options->comp_lzo) lzo_compress (&buf, lzo_compress_buf, &lzo_compwork, &frame, current);#endif#ifdef USE_CRYPTO#ifdef USE_SSL mutex_lock (L_TLS); if (tls_multi) tls_pre_encrypt (tls_multi, &buf, &crypto_options);#endif openvpn_encrypt (&buf, encrypt_buf, &crypto_options, &frame, current);#endif udp_socket_get_outgoing_addr (&buf, &udp_socket, &to_udp_addr);#ifdef USE_CRYPTO#ifdef USE_SSL if (tls_multi) tls_post_encrypt (tls_multi, &buf); mutex_unlock (L_TLS);#endif#endif to_udp = buf; free_to_udp = false; msg (D_PACKET_CONTENT, "SENT PING"); } event_timeout_wakeup (&ping_send_interval, current, &timeval); tv = &timeval; } } /* do a quick garbage collect */ gc_collect (gc_level); /* * Set up for select call. * * Decide what kind of events we want to wait for. */ FD_ZERO (&reads); FD_ZERO (&writes); if (to_udp.len > 0) { if (options->shaper) { /* * If sending this packet would put us over our traffic shaping * quota, don't send -- instead compute the delay we must wait * until it will be OK to send the packet. */ const int delay = shaper_delay (&shaper); /* traffic shaping delay in microseconds */ if (delay) { shaper_soonest_event (&timeval, delay); tv = &timeval; } else { FD_SET (udp_socket.sd, &writes); } } else { FD_SET (udp_socket.sd, &writes); } } else { if (tuntap->fd >= 0) FD_SET (tuntap->fd, &reads);#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD) if (tls_multi) FD_SET (tls_thread_socket, &reads);#endif } if (to_tun.len > 0) { if (tuntap->fd >= 0) FD_SET (tuntap->fd, &writes); } else { FD_SET (udp_socket.sd, &reads); } /* * Possible scenarios: * (1) udp port has data available to read * (2) udp port is ready to accept more data to write * (3) tun dev has data available to read * (4) tun dev is ready to accept more data to write * (5) tls background thread has data available to forward to udp port * (6) we received a signal (handler sets signal_received) * (7) timeout (tv) expired (from TLS, shaper, inactivity timeout, or ping timeout) */ /* * Wait for something to happen. */ if (!signal_received) stat = select (fm, &reads, &writes, NULL, tv); /* current should always be a reasonably up-to-date timestamp */ current = time (NULL); /* * Did we get a signal before or while we were waiting * in select() ? */ if (signal_received) { if (signal_received == SIGUSR2) { msg (M_INFO, "Current OpenVPN Statistics:"); msg (M_INFO, " tun/tap read bytes: " counter_format, tun_read_bytes); msg (M_INFO, " tun/tap write bytes: " counter_format, tun_write_bytes); msg (M_INFO, " UDP read bytes: " counter_format, udp_read_bytes); msg (M_INFO, " UDP write bytes: " counter_format, udp_write_bytes);#ifdef USE_LZO if (options->comp_lzo) lzo_print_stats (&lzo_compwork); #endif signal_received = 0; continue; } /* for all other signals (INT, TERM, HUP, USR1) we break */ switch (signal_received) { case SIGINT: msg (M_INFO, "SIGINT received, exiting"); break; case SIGTERM: msg (M_INFO, "SIGTERM received, exiting"); break; case SIGHUP: msg (M_INFO, "SIGHUP received, restarting"); break; case SIGUSR1: msg (M_INFO, "SIGUSR1 received, restarting"); break; default: msg (M_INFO, "Unknown signal %d received", signal_received); break; } break; }#if defined(USE_CRYPTO) && defined(USE_SSL) if (!stat) /* timeout? */ continue;#endif check_status (stat, "select"); if (stat > 0) { /* Incoming data on UDP port */ if (FD_ISSET (udp_socket.sd, &reads)) { /* * Set up for recvfrom call to read datagram * sent to our UDP port from any source address. */ struct sockaddr_in from; socklen_t fromlen = sizeof (from); ASSERT (!to_tun.len); buf = read_udp_buf; ASSERT (buf_init (&buf, EXTRA_FRAME (&frame))); ASSERT (buf_safe (&buf, max_rw_size_udp)); fromlen = sizeof (from); buf.len = recvfrom (udp_socket.sd, BPTR (&buf), max_rw_size_udp, 0, (struct sockaddr *) &from, &fromlen); ASSERT (fromlen == sizeof (from)); if (buf.len > 0) udp_read_bytes += buf.len; /* check recvfrom status */ check_status (buf.len, "read from UDP"); /* possibly corrupt packet if we are in gremlin test mode */ if (options->gremlin) { if (!ask_gremlin()) buf.len = 0; corrupt_gremlin(&buf); } /* log incoming packet */ msg (D_PACKET_CONTENT, "UDP READ from %s: %s", print_sockaddr (&from), PROTO_DUMP (&buf)); /* * Good, non-zero length packet received. * Commence multi-stage processing of packet, * such as authenticate, decrypt, decompress. * If any stage fails, it sets buf.len to 0, * telling downstream stages to ignore the packet. */ if (buf.len > 0) { udp_socket_incoming_addr (&buf, &udp_socket, &from);#ifdef USE_CRYPTO#ifdef USE_SSL mutex_lock (L_TLS); if (tls_multi) { /* * If tls_pre_decrypt returns true, it means the incoming * packet was a good TLS control channel packet. If so, TLS code * will deal with the packet and set buf.len to 0 so downstream * stages ignore it. * * It the packet is a data channel packet, tls_pre_decrypt * will load crypto_options with the correct encryption key * and return false. */ if (tls_pre_decrypt (tls_multi, &from, &buf, &crypto_options, current)) {#ifdef USE_PTHREAD /* tell TLS thread a packet is waiting */ if (tls_thread_process (tls_thread_socket) == -1) { msg (M_WARN, "TLS thread is not responding, exiting (1)"); signal_received = 0; mutex_unlock (L_TLS); break; }#else interval_trigger(&tmp_int, current);#endif /* USE_PTHREAD */ /* reset packet received timer if TLS packet */ if (options->ping_rec_timeout) event_timeout_reset (&ping_rec_interval, current); } }#endif /* USE_SSL */ /* authenticate and decrypt the incoming packet */ openvpn_decrypt (&buf, decrypt_buf, &crypto_options, &frame, current);#ifdef USE_SSL mutex_unlock (L_TLS);#endif#endif /* USE_CRYPTO */#ifdef USE_LZO /* decompress the incoming packet */ if (options->comp_lzo) lzo_decompress (&buf, lzo_decompress_buf, &lzo_compwork, &frame);#endif /* * Set our "official" outgoing address, since * if buf.len is non-zero, we know the packet * authenticated. In TLS mode we do nothing * because TLS mode takes care of source address * authentication. */ if (!TLS_MODE) udp_socket_set_outgoing_addr (&buf, &udp_socket, &from); /* reset packet received timer */ if (options->ping_rec_timeout && buf.len > 0) event_timeout_reset (&ping_rec_interval, current); /* Did we just receive an openvpn ping packet? */ if (buf_string_match (&buf, ping_string, sizeof (ping_string))) { msg (D_PACKET_CONTENT, "RECEIVED PING"); buf.len = 0; /* drop it */ } to_tun = buf; } else { to_tun = nullbuf; } }#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD) /* Incoming data from TLS background thread */ else if (tls_multi && FD_ISSET (tls_thread_socket, &reads)) { int s; ASSERT (!to_udp.len); s = tls_thread_rec_buf (tls_thread_socket, &tt_ret, true); if (s == 1) { /* * TLS background thread has a control channel * packet to send to remote. */ to_udp = tt_ret.to_udp; to_udp_addr = tt_ret.to_udp_addr; /* tell UDP packet writer to free buffer after write */ free_to_udp = true; } /* remote died? */ else if (s == -1) { msg (M_WARN, "TLS thread is not responding, exiting (2)"); signal_received = 0; break; } }#endif /* Incoming data on TUN device */ else if (tuntap->fd >= 0 && FD_ISSET (tuntap->fd, &reads)) { /* * Setup for read() call on tun/tap device. */ ASSERT (!to_udp.len); buf = read_tun_buf; ASSERT (buf_init (&buf, EXTRA_FRAME (&frame))); ASSERT (buf_safe (&buf, MAX_RW_SIZE_TUN (&frame))); buf.len = read_tun (tuntap, BPTR (&buf), MAX_RW_SIZE_TUN (&frame)); if (buf.len > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -