[PATCH on top of 82d4430] Smarter MTU calculation for GlobalProtect
Daniel Lenski
dlenski at gmail.com
Fri Jan 12 16:10:25 PST 2018
- If we have no ESP support, ESP disabled, or no ESP keys received, then
we're definitely using the TLS tunne and we should calculate tunnel MTU
based on the TCP MSS, subtracting the TLS+GPST overhead (and only use the
base/wire MTU as a crude fallback if necessary).
- If we've got ESP enabled and ESP keys, then we should calculate tunnel
MTU based on the base/wire MTU, subtracting the IP+UDP+ESP overhead.
Signed-off-by: Daniel Lenski <dlenski at gmail.com>
---
gpst.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/gpst.c b/gpst.c
index 87cfbc9..cab05ce 100644
--- a/gpst.c
+++ b/gpst.c
@@ -270,6 +270,7 @@ out:
#define ESP_HEADER_SIZE (4 /* SPI */ + 4 /* sequence number */)
#define ESP_FOOTER_SIZE (1 /* pad length */ + 1 /* next header */)
#define UDP_HEADER_SIZE 8
+#define TCP_HEADER_SIZE 20 /* with no options */
#define IPV4_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40
@@ -281,9 +282,10 @@ out:
static int calculate_mtu(struct openconnect_info *vpninfo)
{
int mtu = vpninfo->reqmtu, base_mtu = vpninfo->basemtu;
+ int mss = 0;
#if defined(__linux__) && defined(TCP_INFO)
- if (!mtu || !base_mtu) {
+ if (!mtu) {
struct tcp_info ti;
socklen_t ti_size = sizeof(ti);
@@ -297,23 +299,19 @@ static int calculate_mtu(struct openconnect_info *vpninfo)
base_mtu = ti.tcpi_pmtu;
}
- if (!base_mtu) {
- if (ti.tcpi_rcv_mss < ti.tcpi_snd_mss)
- base_mtu = ti.tcpi_rcv_mss - 21;
- else
- base_mtu = ti.tcpi_snd_mss - 21;
- }
+ /* XXX: GlobalProtect has no mechanism to inform the server about the
+ * desired MTU, so could just ignore the "incoming" MSS (tcpi_rcv_mss).
+ */
+ mss = MIN(ti.tcpi_rcv_mss, ti.tcpi_snd_mss);
}
}
#endif
#ifdef TCP_MAXSEG
- if (!base_mtu) {
- int mss;
+ if (!mtu && !mss) {
socklen_t mss_size = sizeof(mss);
if (!getsockopt(vpninfo->ssl_fd, IPPROTO_TCP, TCP_MAXSEG,
&mss, &mss_size)) {
vpn_progress(vpninfo, PRG_DEBUG, _("TCP_MAXSEG %d\n"), mss);
- base_mtu = mss - 21;
}
}
#endif
@@ -325,7 +323,11 @@ static int calculate_mtu(struct openconnect_info *vpninfo)
if (base_mtu < 1280)
base_mtu = 1280;
- if (!mtu) {
+#ifdef HAVE_ESP
+ /* If we can use the ESP tunnel (got secrets in config),
+ * then we should pick the optimal MTU for ESP.
+ */
+ if (!mtu && vpninfo->dtls_state == DTLS_SECRET) {
/* remove ESP, UDP, IP headers from base (wire) MTU */
mtu = ( base_mtu - UDP_HEADER_SIZE - ESP_HEADER_SIZE
- 12 /* both supported algos (SHA1 and MD5) have 96-bit MAC lengths (RFC2403 and RFC2404) */
@@ -338,6 +340,23 @@ static int calculate_mtu(struct openconnect_info *vpninfo)
mtu -= mtu % (vpninfo->enc_key_len ? : 32);
/* subtract ESP footer, which is included in the payload before padding to the blocksize */
mtu -= ESP_FOOTER_SIZE;
+
+ } else
+#endif
+
+ /* We are definitely using the TLS tunnel (no ESP secrets)
+ * so we should base our MTU on the TCP MSS.
+ */
+ if (!mtu) {
+ if (mss)
+ mtu = mss - 21;
+ else {
+ mtu = base_mtu - TCP_HEADER_SIZE - 21;
+ if (vpninfo->peer_addr->sa_family == AF_INET6)
+ mtu -= IPV6_HEADER_SIZE;
+ else
+ mtu -= IPV4_HEADER_SIZE;
+ }
}
return mtu;
}
--
2.7.4
More information about the openconnect-devel
mailing list