The
.B algorithm
-parameter may be "lzo", "lz4", or empty. LZO and LZ4
-are different compression algorithms, with LZ4 generally
+parameter may be "lzo", "lz4", "lz4\-v2", "stub", "stub\-v2" or empty.
+LZO and LZ4 are different compression algorithms, with LZ4 generally
offering the best performance with least CPU usage.
For backwards compatibility with OpenVPN versions before v2.4, use "lzo"
(which is identical to the older option "\-\-comp\-lzo yes").
+The "lz4\-v2" and "stub\-v2" variants implement a better framing that does not add
+overhead when packets cannot be compressed. All other variants always add one extra
+framing byte compared to no compression framing.
+
If the
.B algorithm
-parameter is empty, compression will be turned off, but the packet
-framing for compression will still be enabled, allowing a different
-setting to be pushed later.
+parameter is "stub", "stub\-v2", or empty, compression will be turned off, but
+the packet framing for compression will still be enabled, allowing a different
+setting to be pushed later. Additionally, "stub" and "stub\-v2" will disable
+announcing lzo and lz4 compression support via "IV_" variables to the server.
+
.B Security Considerations
Compression and encryption is a tricky combination. If an attacker knows or is
able to control (parts of) the plaintext of packets that contain secrets, the
attacker might be able to extract the secret if compression is enabled. See
-e.g. the CRIME and BREACH attacks on TLS which also leverage compression to
-break encryption. If you are not entirely sure that the above does not apply
-to your traffic, you are advised to *not* enable compression.
+e.g. the CRIME and BREACH attacks on TLS and VORACLE on VPNs which also leverage
+compression to break encryption. If you are not entirely sure that the above does
+not apply to your traffic, you are advised to *not* enable compression.
+
+.\"*********************************************************
+.TP
+.B \-\-allow\-compression [mode]
+As described in
+\.B \-\-compress
+option, compression is potentially dangerous option. This option allows
+controlling the behaviour of OpenVPN when compression is used and allowed.
+.B mode
+may be "yes", "no", or "asym" (default).
+
+With allow\-compression set to "no", OpenVPN will refuse any non stub
+compression. With "yes" OpenVPN will send and receive compressed packets.
+With "asym", the default, OpenVPN will only decompress (downlink) packets but
+not compress (uplink) packets. This also allows migrating to disable compression
+when changing both server and client configurations to remove compression at the
+same time is not a feasible option.
+
+The default of asym has been chosen to maximise compatibility with existing
+configuration while at the same time phasing out compression in existing
+deployment by disabling compression on the uplink, effectively completely disabling
+compression if both client and server are upgraded.
.\"*********************************************************
.TP
#endif
#if defined(USE_COMP)
"--compress alg : Use compression algorithm alg\n"
+ "--allow-compression: Specify whether compression should be allowed\n"
#if defined(ENABLE_LZO)
"--comp-lzo : Use LZO compression -- may add up to 1 byte per\n"
- " packet for uncompressible data.\n"
+ " packet for incompressible data.\n"
"--comp-noadapt : Don't use adaptive compression when --comp-lzo\n"
" is specified.\n"
#endif
#if P2MP
#define VERIFY_PERMISSION(mask) { \
- if (!verify_permission(p[0], file, line, (mask), permission_mask, \
- option_types_found, msglevel, options, is_inline))\
- { \
- goto err; \
- } \
+ if (!verify_permission(p[0], file, line, (mask), permission_mask, \
+ option_types_found, msglevel, options, is_inline)) \
+ { \
+ goto err; \
+ } \
}
static bool
#endif
}
+static void
+show_compression_warning(struct compress_options *info)
+{
+ if (comp_non_stub_enabled(info))
+ {
+ /*
+ * Check if already displayed the strong warning and enabled full
+ * compression
+ */
+ if (!(info->flags & COMP_F_ALLOW_COMPRESS))
+ {
+ msg(M_WARN, "WARNING: Compression for receiving enabled. "
+ "Compression has been used in the past to break encryption. "
+ "Sent packets are not compressed unless \"allow-compression yes\" "
+ "is also set.");
+ }
+ }
+}
+
static void
add_option(struct options *options,
char *p[],
}
#endif
#if defined(USE_COMP)
+ else if (streq(p[0], "allow-compression") && p[1] && !p[2])
+ {
+ VERIFY_PERMISSION(OPT_P_GENERAL);
+
+ if (streq(p[1], "no"))
+ {
+ options->comp.flags =
+ COMP_F_ALLOW_STUB_ONLY|COMP_F_ADVERTISE_STUBS_ONLY;
+ if (comp_non_stub_enabled(&options->comp))
+ {
+ msg(msglevel, "'--allow-compression no' conflicts with "
+ " enabling compression");
+ }
+ }
+ else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
+ {
+ /* Also printed on a push to hint at configuration problems */
+ msg(msglevel, "Cannot set allow-compression to '%s' "
+ "after set to 'no'", p[1]);
+ goto err;
+ }
+ else if (streq(p[1], "asym"))
+ {
+ options->comp.flags &= ~COMP_F_ALLOW_COMPRESS;
+ }
+ else if (streq(p[1], "yes"))
+ {
+ msg(M_WARN, "WARNING: Compression for sending and receiving enabled. Compression has "
+ "been used in the past to break encryption. Allowing compression allows "
+ "attacks that break encryption. Using \"--allow-compression yes\" is "
+ "strongly discouraged for common usage. See --compress in the manual "
+ "page for more information ");
+
+ options->comp.flags |= COMP_F_ALLOW_COMPRESS;
+ }
+ else
+ {
+ msg(msglevel, "bad allow-compression option: %s -- "
+ "must be 'yes', 'no', or 'asym'", p[1]);
+ goto err;
+ }
+ }
else if (streq(p[0], "comp-lzo") && !p[2])
{
VERIFY_PERMISSION(OPT_P_COMP);
+ /* All lzo variants do not use swap */
+ options->comp.flags &= ~COMP_F_SWAP;
#if defined(ENABLE_LZO)
if (p[1] && streq(p[1], "no"))
#endif
{
options->comp.alg = COMP_ALG_STUB;
- options->comp.flags = 0;
+ options->comp.flags &= ~COMP_F_ADAPTIVE;
}
#if defined(ENABLE_LZO)
+ else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
+ {
+ /* Also printed on a push to hint at configuration problems */
+ msg(msglevel, "Cannot set comp-lzo to '%s', "
+ "allow-compression is set to 'no'", p[1]);
+ goto err;
+ }
else if (p[1])
{
if (streq(p[1], "yes"))
{
options->comp.alg = COMP_ALG_LZO;
- options->comp.flags = 0;
+ options->comp.flags &= ~COMP_F_ADAPTIVE;
}
else if (streq(p[1], "adaptive"))
{
options->comp.alg = COMP_ALG_LZO;
- options->comp.flags = COMP_F_ADAPTIVE;
+ options->comp.flags |= COMP_F_ADAPTIVE;
}
else
{
else
{
options->comp.alg = COMP_ALG_LZO;
- options->comp.flags = COMP_F_ADAPTIVE;
+ options->comp.flags |= COMP_F_ADAPTIVE;
}
+ show_compression_warning(&options->comp);
#endif /* if defined(ENABLE_LZO) */
}
else if (streq(p[0], "comp-noadapt") && !p[1])
{
+ /*
+ * We do not need to check here if we allow compression since
+ * it only modifies a flag if compression is enabled
+ */
VERIFY_PERMISSION(OPT_P_COMP);
options->comp.flags &= ~COMP_F_ADAPTIVE;
}
if (streq(p[1], "stub"))
{
options->comp.alg = COMP_ALG_STUB;
- options->comp.flags = (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
+ options->comp.flags |= (COMP_F_SWAP|COMP_F_ADVERTISE_STUBS_ONLY);
}
else if (streq(p[1], "stub-v2"))
{
options->comp.alg = COMP_ALGV2_UNCOMPRESSED;
- options->comp.flags = COMP_F_ADVERTISE_STUBS_ONLY;
+ options->comp.flags |= COMP_F_ADVERTISE_STUBS_ONLY;
+ }
+ else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY)
+ {
+ /* Also printed on a push to hint at configuration problems */
+ msg(msglevel, "Cannot set compress to '%s', "
+ "allow-compression is set to 'no'", p[1]);
+ goto err;
}
#if defined(ENABLE_LZO)
else if (streq(p[1], "lzo"))
{
options->comp.alg = COMP_ALG_LZO;
- options->comp.flags = 0;
+ options->comp.flags &= ~(COMP_F_ADAPTIVE | COMP_F_SWAP);
}
#endif
#if defined(ENABLE_LZ4)
else if (streq(p[1], "lz4"))
{
options->comp.alg = COMP_ALG_LZ4;
- options->comp.flags = COMP_F_SWAP;
+ options->comp.flags |= COMP_F_SWAP;
}
else if (streq(p[1], "lz4-v2"))
{
options->comp.alg = COMP_ALGV2_LZ4;
- options->comp.flags = 0;
}
#endif
else
else
{
options->comp.alg = COMP_ALG_STUB;
- options->comp.flags = COMP_F_SWAP;
+ options->comp.flags |= COMP_F_SWAP;
}
+ show_compression_warning(&options->comp);
}
#endif /* USE_COMP */
else if (streq(p[0], "show-ciphers") && !p[1])