Make compression asymmetric by default and add warnings
PATCH v2 1/1 Make compression asymmetric by default and add warnings
In reply to a message not in the archiveThis commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning are not generated in the post option check (options_postprocess_mutate) since these warnings should also be shown on pushed options.
Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source code
--- doc/openvpn.8 | 44 +++++++++++++++++---- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 ++++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 90 ++++++++++++++++++++++++++++++++++++------ 7 files changed, 132 insertions(+), 27 deletions(-)
doc/openvpn.8 +36 -8
@@ -2508,26 +2508,54 @@ Enable a compression algorithm. 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
src/openvpn/comp-lz4.c +2 -1
@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_NO_ASYM )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);
src/openvpn/comp.c +1 -1
@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }
src/openvpn/comp.h +13 -3
@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_NO_ASYM (1<<1)/* not only downlink is compressed but also uplink */ +#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /*
@@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info) +{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED && + info->alg !=COMP_ALG_STUB && + info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {
src/openvpn/lzo.c +1 -1
@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_NO_ASYM )) {return false; }
src/openvpn/mtu.h +1 -1
@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /*
src/openvpn/options.c +78 -12
177 lines not on this page · raw message
Signature · 1 line
2.18.0
PATCH v3 1/1 Make compression asymmetric by default and add warnings
This commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning are not generated in the post option check (options_postprocess_mutate) since these warnings should also be shown on pushed options.
Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source code
Patch V3: fix overlong lines. Do not allow compression to be pushed
--- doc/openvpn.8 | 44 ++++++++++++++---- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 +++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 101 ++++++++++++++++++++++++++++++++++++----- 7 files changed, 143 insertions(+), 27 deletions(-)
doc/openvpn.8 +36 -8
@@ -2545,26 +2545,54 @@ Enable a compression algorithm. 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
src/openvpn/comp-lz4.c +2 -1
@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_NO_ASYM )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);
src/openvpn/comp.c +1 -1
@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }
src/openvpn/comp.h +13 -3
@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_NO_ASYM (1<<1)/* not only downlink is compressed but also uplink */ +#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /*
@@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info) +{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED && + info->alg !=COMP_ALG_STUB && + info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {
src/openvpn/lzo.c +1 -1
@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_NO_ASYM )) {return false; }
src/openvpn/mtu.h +1 -1
@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /*
src/openvpn/options.c +89 -12
188 lines not on this page · raw message
Signature · 1 line
2.19.0
Hi,
Feature-ack, and overall looks good. But some nits to tackle.
Quoted 123 lines · Arne Schwabe
This commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning are not generated in the post option check (
options_postprocess_mutate) since these warnings should also be shown on pushed options.Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source codePatch V3: fix overlong lines. Do not allow compression to be pushed
--- doc/openvpn.8 | 44 ++++++++++++++---- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 +++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 101 ++++++++++++++++++++++++++++++++++++----- 7 files changed, 143 insertions(+), 27 deletions(-)doc/openvpn.8 +36
-8@@ -2545,26 +2545,54 @@ Enable a compression algorithm. 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. .\"********************************************************* .TPsrc/openvpn/comp-lz4.c +2
-1@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_NO_ASYM )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);src/openvpn/comp.c +1
-1@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }src/openvpn/comp.h +0
-0
src/openvpn/comp.h line 56
Quoted 8 lines
src/openvpn/comp.h +2
-3@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_NO_ASYM (1<<1)/* not only downlink is compressed but also uplink */
Negative names confuse me. How about COMP_F_ALLOW_COMPRESS?
src/openvpn/comp.h comp_enabled(const struct compress_options *info) · line 194
Quoted 13 lines
src/openvpn/comp.h +5
-0+#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /* @@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info)
There should be no space between function name and (
Quoted 40 lines
src/openvpn/comp.h +6
-0+{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED && + info->alg !=COMP_ALG_STUB && + info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {src/openvpn/lzo.c +1
-1@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_NO_ASYM )) {return false; }src/openvpn/mtu.h +1
-1@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /* src/openvpn/options.c +0
-0
src/openvpn/options.c static const char usage_message[] = · line 354
Quoted 4 lines
src/openvpn/options.c +1
-0@@ -351,9 +351,10 @@ static const char usage_message[] =#endif #if defined(USE_COMP )"--compress alg : Use compression algorithm alg\n" +"--allow-compression: Specify wether compression should be allowed\n"
Typo: whether.
Quoted 37 lines
src/openvpn/options.c +20
-1#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 @@ -4901,6 +4902,22 @@ set_user_script(struct options *options,#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_NO_ASYM )) + { +msg (M_WARN ,"WARNING: Compression enabled, Compression has been " +"used in the past to break encryption. Enabling decompression " +"of received packet only. Sent packets are not compressed." ); + } + } +} static void add_option(struct options *options,@@ -7322,29 +7339,78 @@ add_option(struct options *options, }#endif #if defined(USE_COMP ) + else if (streq(p[0], "allow-compression") && p[1] && !p[2]) + { +VERIFY_PERMISSION (OPT_P_GENERAL );
src/openvpn/options.c add_option(struct options *options, · line 7354
Quoted 10 lines
src/openvpn/options.c +10
-0+ +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" ); + }
Should this check not be moved to the postprocess checks? This will now only trigger is comp was first set, and allow-compression later in the config, not the other way around.
Quoted 16 lines
src/openvpn/options.c +16
-0+ } +else if (options->comp.flags &COMP_F_ALLOW_STUB_ONLY ) + { +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_NO_ASYM ; + } +else if (streq (p[1 ],"yes" )) + { +msg (M_WARN ,"WARNING: Compression enabled, Compression has been" +"used in the past to break encryption. " + "Allowing compression allows attacks that break encryption. "
src/openvpn/options.c add_option(struct options *options, · line 7380
Quoted 10 lines
src/openvpn/options.c +10
-0+"Using '--allow-compression yes' is strongly discouraged for " +"common usage. " + "See --compress in the manual page for more information"); + options->comp.flags |=COMP_F_NO_ASYM ; + } +else + { +msg (msglevel,"bad allow-compression option: %s -- " +"must be 'yes', 'no', or 'asym'" , p[1 ]); + goto err;
Indenting looks off.
Quoted 100 lines
src/openvpn/options.c +29
-9+ } + }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) + { + 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 {@@ -7355,12 +7421,17 @@ add_option(struct options *options, 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 ; }@@ -7372,30 +7443,35 @@ add_option(struct options *options,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 ) + { +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
src/openvpn/options.c add_option(struct options *options, · line 7488
Quoted 7 lines
src/openvpn/options.c +2
-1@@ -7407,8 +7483,9 @@ add_option(struct options *options,else { options->comp.alg =COMP_ALG_STUB ; - options->comp.flags =COMP_F_SWAP ; + options->comp.flags |=COMP_F_SWAP ; } +show_compression_warning (&options->comp);
Indenting?
src/openvpn/options.c add_option(struct options *options, · line 8393
Quoted 11 lines
src/openvpn/options.c +1
-1}#endif /* USE_COMP */ else if (streq(p[0], "show-ciphers") && !p[1])@@ -8313,4 +8390,4 @@ add_option(struct options *options, } err:gc_free (&gc); -} +}
Unneeded change.
-Steffan
Quoted 14 lines · Steffan Karger
Quoted 14 lines
static void
add_option(struct options *options,src/openvpn/options.c +8
-0@@ -7322,29 +7339,78 @@ add_option(struct options *options, }#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 ;
Quoted 8 lines
src/openvpn/options.c add_option(struct options *options, · line 7354
Quoted 5 lines
src/openvpn/options.c +5
-0+if (comp_non_stub_enabled (&options->comp)) + { +msg (msglevel,"'--allow-compression no' conflicts with " +" enabling compression" ); + }Should this check not be moved to the postprocess checks? This will now only trigger is comp was first set, and allow-compression later in the config, not the other way around.
What about pushed options? It's too long time since I looked at the option parsing code paths last time, so I don't remember all the quirks here.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Inc
Am 10.11.19 um 10:55 schrieb David Sommerseth:
Quoted 24 lines · Steffan Karger
Quoted 14 lines
Quoted 14 lines
static void
add_option(struct options *options,src/openvpn/options.c +8
-0@@ -7322,29 +7339,78 @@ add_option(struct options *options, }#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 ;Quoted 8 lines
src/openvpn/options.c add_option(struct options *options, · line 7354
Quoted 5 lines
src/openvpn/options.c +5
-0+if (comp_non_stub_enabled (&options->comp)) + { +msg (msglevel,"'--allow-compression no' conflicts with " +" enabling compression" ); + }Should this check not be moved to the postprocess checks? This will now only trigger is comp was first set, and allow-compression later in the config, not the other way around.
Quoted 2 lines
What about pushed options? It's too long time since I looked at the option parsing code paths last time, so I don't remember all the quirks here.
For pushed options msglevel will be warning so you get a warning when the server tries to enable compression but it will not error out. The server pushing a compression when the client does not advertise the IV_ for that algorithm is an error in the server config.
Arne
PATCH v4 1/1 Make compression asymmetric by default and add warnings
In reply to Steffan KargerThis commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning for comp-lzo/compress are not generated in the post option check (options_postprocess_mutate) since these warnings should also be shown on pushed options. Moving the showing the warning showing for allow-compression to options_postprocess_mutate will complicate the option handling without giving any other benefit.
Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source code
Patch V3: fix overlong lines. Do not allow compression to be pushed
Patch V4: rename COMP_F_NO_ASYM to COMP_F_ALLOW_COMPRESS, fix style.
The logic of warnings etc in options.c has not been changed since adding all the code to mutate_options would a lot more and more complicated code and after discussion we decided that it is okay as is.
--- doc/openvpn.8 | 44 +++++++++++++---- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 +++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 105 ++++++++++++++++++++++++++++++++++++----- 7 files changed, 147 insertions(+), 27 deletions(-)
doc/openvpn.8 +36 -8
@@ -2545,26 +2545,54 @@ Enable a compression algorithm. 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
src/openvpn/comp-lz4.c +2 -1
@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_ALLOW_COMPRESS )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);
src/openvpn/comp.c +1 -1
@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }
src/openvpn/comp.h +13 -3
@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_ALLOW_COMPRESS (1<<1)/* not only downlink is compressed but also uplink */ +#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /*
@@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info) +{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED + && info->alg !=COMP_ALG_STUB + && info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {
src/openvpn/lzo.c +1 -1
@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_ALLOW_COMPRESS )) {return false; }
src/openvpn/mtu.h +1 -1
@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /*
src/openvpn/options.c +93 -12
192 lines not on this page · raw message
Signature · 1 line
2.25.0
Hi,
Quoted 3 lines
Warning for comp-lzo/compress are not generated in the post option check (
options_postprocess_mutate) since these warnings should also be shown on pushed options. Moving the showing the warning showing for
Typo in the last sentence.
If I want to use compression and specify algorithm, I got confusing warnings:
➜ openvpn git:(master) ✗ sudo src/openvpn/openvpn --config ~/lev.ovpn --compress lz4-v2 --allow-compression yes
Thu May 14 16:16:26 2020 WARNING: Compression enabled, Compression has been used in the past to break encryption. Enabling decompression of received packet only. Sent packets are not compressed. Thu May 14 16:16:26 2020 WARNING: Compression enabled, Compression has beenused 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
Thu May 14 16:16:26 2020 OpenVPN 2.5_git [git:master/6001784afd89c4e9+] x86_64-apple-darwin19.4.0 [SSL (OpenSSL)] [LZO] [LZ4] [MH/RECVDA] [AEAD] built on May 14 2020
1) The first warning is wrong, since I explicitly allowed compression. Also it has unneeded whitespace in the beginning.
2) The second warning is missing whitespace ("beenused").
Quoted 4 lines
The logic of warnings etc in
options.chas not been changed since adding all the code tomutate_optionswould a lot more and more complicated code and after discussion we decided that it is okay as is.
Cannot we set some bit flags in options processing, like
COMP_WARN_GENERIC 1 << 0 // Compression enabled, Compression has been used in the past to break encryption.COMP_WARN_ASYNC 1 << 1 // Enabling decompression of received packet only. Sent packets are not compressed. COMP_WARN_ALLOWED_YES 1 << 2 // Using '--allow-compression yes' is strongly discouraged for common usage. See --compress in the manual page for more information
and handle them in options postprocessing - excluding COMP_ENABLED_WARN_ASYNC if COMP_ENABLED_WARN_YES is set and printing the message?
Signature · 1 line
-Lev
Quoted 11 lines
Cannot we set some bit flags in options processing, like
COMP_WARN_GENERIC1 << 0 // Compression enabled, Compression has been used in the past to break encryption.COMP_WARN_ASYNC1 << 1 // Enabling decompression of received packet only. Sent packets are not compressed.COMP_WARN_ALLOWED_YES1 << 2 // Using '--allow-compression yes' is strongly discouraged for common usage. See --compress in the manual page for more information
Quoted 4 lines
and handle them in options postprocessing - excluding
COMP_ENABLED_WARN_ASYNCifCOMP_ENABLED_WARN_YESis set and printing the message?
Same explaination as last time when Steffan reviewed this patch. The warning should also show up in pushed options. And I don't want to complicate the logic for to avoid an extra warning for a corner case. We reword the message a bit so that two messages are not that bad if both are shown:
WARNING: Compression for receiving enabled, Compression
has been used in the past to break encryption. Sent packet are not compress unless "allow-compression yes" is also set.
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
Hi,
Apologize for delay.
I tested with various combinations of flags and code works as expected.
Let's reword messages as you proposed:
Quoted 5 lines
We reword the message a bit so that two messages are not that bad if both are shown:
WARNING: Compression for receiving enabled, Compression
has been used in the past to break encryption. Sent packet are not compress unless "allow-compression yes" is also set.
A small typo:
.. Sent packets are not compressed ...
Quoted 7 lines
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
Signature · 1 line
-Lev
Hi,
Quoted 1 line · Lev Stipakov
Semi-acked-by Lev-Stipakov <[email protected]...>
Is that an "ACKed if Gert changes the text of the message as suggested" (which is a typo, so okay-ish), or "Arne should send a new version"?
gert
Signature · 6 lines
"If was one thing all people took for granted, was conviction that if you
feed honest figures into a computer, honest figures come out. Never doubted
it myself till I met a computer with a sense of humor."
Robert A. Heinlein, The Moon is a Harsh Mistress
Gert Doering - Munich, Germany [email protected]...Hi,
Quoted 2 lines
Is that an "ACKed if Gert changes the text of the message as suggested" (which is a typo, so okay-ish),
Yes, ACKed if the committer (Gert) will change the message.
PATCH v5 1/1 Make compression asymmetric by default and add warnings
In reply to Arne SchwabeThis commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning for comp-lzo/compress are not generated in the post option check (options_postprocess_mutate) since these warnings should also be shown on pushed options. Moving the showing the warning showing for allow-compression to options_postprocess_mutate will complicate the option handling without giving any other benefit.
Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source code
Patch V3: fix overlong lines. Do not allow compression to be pushed
Patch V4: rename COMP_F_NO_ASYM to COMP_F_ALLOW_COMPRESS, fix style.
The logic of warnings etc in options.c has not been changed since adding all the code to mutate_options would a lot more and more complicated code and after discussion we decided that it is okay as is.
Patch V5: Reword warnings, rebase on master
--- doc/openvpn.8 | 44 +++++++++++++--- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 ++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 115 +++++++++++++++++++++++++++++++++++------ 7 files changed, 153 insertions(+), 31 deletions(-)
doc/openvpn.8 +36 -8
@@ -2545,26 +2545,54 @@ Enable a compression algorithm. 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
src/openvpn/comp-lz4.c +2 -1
@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_ALLOW_COMPRESS )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);
src/openvpn/comp.c +1 -1
@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }
src/openvpn/comp.h +13 -3
@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_ALLOW_COMPRESS (1<<1)/* not only downlink is compressed but also uplink */ +#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /*
@@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info) +{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED + && info->alg !=COMP_ALG_STUB + && info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {
src/openvpn/lzo.c +1 -1
@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_ALLOW_COMPRESS )) {return false; }
src/openvpn/mtu.h +1 -1
@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /*
src/openvpn/options.c +99 -16
204 lines not on this page · raw message
Signature · 1 line
2.26.2
Checked that only diffs are warning messages (as agreed) and different indentation in #define VERIFY_PERMISSION (probably caused by uncrustify).
pe 26. kesäk. 2020 klo 14.06 Arne Schwabe ([email protected]...) kirjoitti:
Quoted 416 lines
This commit introduces the allow-compression option that allow changing the new default to the previous default or to a stricter version.
Warning for comp-lzo/compress are not generated in the post option check (
options_postprocess_mutate) since these warnings should also be shown on pushed options. Moving the showing the warning showing for allow-compression tooptions_postprocess_mutatewill complicate the option handling without giving any other benefit.Patch V2: fix spelling and grammer (thanks tincantech), also fix
uncompressiable to incompressible in three other instances in the source codePatch V3: fix overlong lines. Do not allow compression to be pushed
Patch V4: rename
COMP_F_NO_ASYMtoCOMP_F_ALLOW_COMPRESS, fix style.
The logic of warnings etc inoptions.chas not been changed since adding all the code tomutate_optionswould a lot more and more complicated code and after discussion we decided that it is okay as is.Patch V5: Reword warnings, rebase on master
Signed-off-by Arne Schwabe <[email protected]...>--- doc/openvpn.8 | 44 +++++++++++++--- src/openvpn/comp-lz4.c | 3 +- src/openvpn/comp.c | 2 +- src/openvpn/comp.h | 16 ++++-- src/openvpn/lzo.c | 2 +- src/openvpn/mtu.h | 2 +- src/openvpn/options.c | 115 +++++++++++++++++++++++++++++++++++------ 7 files changed, 153 insertions(+), 31 deletions(-)doc/openvpn.8 +36
-8@@ -2545,26 +2545,54 @@ Enable a compression algorithm. 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. .\"********************************************************* .TPsrc/openvpn/comp-lz4.c +2
-1@@ -70,8 +70,9 @@ do_lz4_compress(struct buffer *buf, {/* * In order to attempt compression, length must be at least COMPRESS_THRESHOLD. +* and asymmetric compression must be disabled */ -if (buf->len >=COMPRESS_THRESHOLD ) +if (buf->len >=COMPRESS_THRESHOLD && (compctx->flags &COMP_F_ALLOW_COMPRESS )) {const size_t ps =PAYLOAD_SIZE (frame);int zlen_max = ps +COMP_EXTRA_BUFFER (ps);src/openvpn/comp.c +1
-1@@ -127,7 +127,7 @@ void comp_add_to_extra_buffer(struct frame *frame) {/* Leave room for compression buffer to expand in worst case scenario -* where data is totally uncompressible */ +* where data is totally incompressible */ frame_add_to_extra_buffer (frame,COMP_EXTRA_BUFFER (EXPANDED_SIZE (frame))); }src/openvpn/comp.h +13
-3@@ -52,10 +52,12 @@*/ /* Compression flags */ -#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ -#define COMP_F_ASYM (1<<1)/* only downlink is compressed, not uplink */ -#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_ADAPTIVE (1<<0)/* COMP_ALG_LZO only */ +#define COMP_F_ALLOW_COMPRESS (1<<1)/* not only downlink is compressed but also uplink */ +#define COMP_F_SWAP (1<<2)/* initial command byte is swapped with last byte in buffer to preserve payload alignment */ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3)/* tell server that we only support compression stubs */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4)/* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY +* we still accept other compressions to be pushed */ /* @@ -188,6 +190,14 @@ comp_enabled(const struct compress_options *info)return info->alg !=COMP_ALG_UNDEF ; } +static inline bool +comp_non_stub_enabled (const struct compress_options *info) +{ +return info->alg !=COMP_ALGV2_UNCOMPRESSED + && info->alg !=COMP_ALG_STUB + && info->alg !=COMP_ALG_UNDEF ; +} +static inline bool comp_unswapped_prefix (const struct compress_options *info) {src/openvpn/lzo.c +1
-1@@ -123,7 +123,7 @@ lzo_compress_uninit(struct compress_context *compctx)static inline bool lzo_compression_enabled (struct compress_context *compctx) { -if (compctx->flags &COMP_F_ASYM ) +if (!(compctx->flags &COMP_F_ALLOW_COMPRESS )) {return false; }src/openvpn/mtu.h +1
-1@@ -45,7 +45,7 @@* ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 * * Compression overflow bytes is the worst-case size expansion that would be -* expected if we tried to compress mtu + extra_frame bytes of uncompressible data. +* expected if we tried to compress mtu + extra_frame bytes of incompressible data. */ /* src/openvpn/options.c +99
-17@@ -357,9 +357,10 @@ static const char usage_message[] =#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 @@ -4978,11 +4979,11 @@ options_string_import(struct options *options,#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@@ -5115,6 +5116,25 @@ set_user_script(struct options *options,#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[],@@ -7606,29 +7626,80 @@ add_option(struct options *options, }#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 {@@ -7639,12 +7710,17 @@ add_option(struct options *options, 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 ; }@@ -7656,30 +7732,36 @@ add_option(struct options *options,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@@ -7691,8 +7773,9 @@ add_option(struct options *options, 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]) --2.26.2
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Signature · 1 line
-Lev
Your patch has been applied to the master branch.
Lightly tested, aka "t_client test on FreeBSD and Linux", which does use various lzo/lz4 variants - so it's not breaking existing setups (though it might turn off compression :-) - which I have not verified)
David: this brings in a sizeable manpage change - please transform in a suitable way into your tree... (unfortunate, but not fully avoidable)
commit c67e93b25208be2e893473bea4aabccbde914f47
Author: Arne Schwabe Date: Fri Jun 26 13:05:54 2020 +0200
Make compression asymmetric by default and add warnings
Signed-off-by: Arne Schwabe <[email protected]...>
Acked-by: Lev Stipakov <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg20138.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering