📜 ⬆️ ⬇️

Linux VPN server - addressing MPPE and non-encryption clients

Historically, a bunch of pptpd + pppd is quite a popular solution for distributing the Internet on local networks, largely due to the presence of the pptp client in windows starting at 98 out of the box. Moreover, this client supports the MPPE encryption protocol which, from windows 2000 on, is enabled for new connections by default.
pppd happily meets us, also supporting this protocol, but does it in a very peculiar way:


quote from README.MPPE:

MPPE * must * be negotiated (CCP is unidirectional) or it will be disconnected. I think this is reasonable, if you want encryption, you want encryption. I am not ready
')
In practice, this means that by including support for mppe (with the options + mppe or require-mppe) you will not be able to serve connections from clients that do not support this protocol. The pppd developers consider this to be quite the correct behavior, stating that “people do not need optional encryption”

But what about those who, in addition to the Windows clients, also have quite a few connections of cheap hardware routers that simply do not support MPPE? Disable encryption for everyone? Or convince customers that they need a router 5 times more expensive?

Before hitting such extremes, it was decided to fix this "feature" and after a couple of hours of thoughtful examination of the pppd sources, a patch was born:
(tested on ppp-2.4.4rel-10.1 from debian lenny)

diff -ruNp ppp-2.4.4.orig/pppd/auth.c ppp-2.4.4/pppd/auth.c
--- ppp-2.4.4.orig/pppd/auth.c 2006-06-18 14:26:00.000000000 +0300
+++ ppp-2.4.4/pppd/auth.c 2008-02-13 18:24:08.000000000 +0200
@@ -875,7 +875,7 @@ start_networks(unit)
*/
ecp_required = ecp_gotoptions[unit].required;
mppe_required = ccp_gotoptions[unit].mppe;
- if (!ecp_required && !mppe_required)
+ if (!ecp_required && (!mppe_required || allow_mppe_fallback))
continue_networks(unit);
}
diff -ruNp ppp-2.4.4.orig/pppd/ccp.c ppp-2.4.4/pppd/ccp.c
--- ppp-2.4.4.orig/pppd/ccp.c 2005-07-09 03:23:05.000000000 +0300
+++ ppp-2.4.4/pppd/ccp.c 2008-02-13 18:31:16.000000000 +0200
@@ -156,6 +156,11 @@ static option_t ccp_option_list[] = {
"allow MPPE stateful mode", OPT_PRIO },
{ "nomppe-stateful", o_bool, &refuse_mppe_stateful,
"disallow MPPE stateful mode", OPT_PRIO | 1 },
+
+ /* allow falling back to unencrypted connection mode */
+ { "mppe-optional", o_bool, &allow_mppe_fallback,
+ "allow falling back to unencryped connection mode", OPT_PRIO | 1 },
+
#endif /* MPPE */
{ NULL }
@@ -516,9 +521,14 @@ ccp_protrej(unit)
#ifdef MPPE
if (ccp_gotoptions[unit].mppe) {
- error("MPPE required but peer negotiation failed");
- lcp_close(unit, "MPPE required but peer negotiation failed");
- }
+ if(!allow_mppe_fallback) {
+ error("MPPE required but peer negotiation failed");
+ lcp_close(unit, "MPPE required but peer negotiation failed");
+ } else {
+ error("MPPE required but peer negotiation failed.");
+ error("Falling back and disabling MPPE");
+ }
+ }
#endif
}
@@ -1004,11 +1014,17 @@ ccp_rejci(f, p, len)
#ifdef MPPE
if (go->mppe && len >= CILEN_MPPE
&& p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
- error("MPPE required but peer refused");
- lcp_close(f->unit, "MPPE required but peer refused");
- p += CILEN_MPPE;
- len -= CILEN_MPPE;
+ if(!allow_mppe_fallback) {
+ error("MPPE required but peer refused. Closing LCP");
+ lcp_close(f->unit, "MPPE required but peer refused");
+ } else {
+ try.mppe = 0;
+ error("MPPE required but peer refused.");
+ error("Falling back and disabling MPPE");
+ }
}
+ p += CILEN_MPPE;
+ len -= CILEN_MPPE;
#endif
if (go->deflate_correct && len >= CILEN_DEFLATE
&& p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
diff -ruNp ppp-2.4.4.orig/pppd/ccp.h ppp-2.4.4/pppd/ccp.h
--- ppp-2.4.4.orig/pppd/ccp.h 2004-11-04 12:02:26.000000000 +0200
+++ ppp-2.4.4/pppd/ccp.h 2008-02-13 19:03:43.000000000 +0200
@@ -43,6 +43,8 @@ typedef struct ccp_options {
short method; /* code for chosen compression method */
} ccp_options;
+bool allow_mppe_fallback;
+
extern fsm ccp_fsm[];
extern ccp_options ccp_wantoptions[];
extern ccp_options ccp_gotoptions[];
@@ -50,3 +52,5 @@ extern ccp_options ccp_allowoptions[];
extern ccp_options ccp_hisoptions[];
extern struct protent ccp_protent;
+
+
diff -ruNp ppp-2.4.4.orig/pppd/pppd.8 ppp-2.4.4/pppd/pppd.8
--- ppp-2.4.4.orig/pppd/pppd.8 2006-06-16 03:01:23.000000000 +0300
+++ ppp-2.4.4/pppd/pppd.8 2008-02-13 18:41:31.000000000 +0200
@@ -770,6 +770,9 @@ available under Linux.
.B nomppe
Disables MPPE (Microsoft Point to Point Encryption). This is the default.
.TP
+.B mppe-optional
+Makes MPPE optional, allowing both MPPE and non-MPPE clients
+.TP
.B nomppe\-40
Disable 40-bit encryption with MPPE.
.TP


After overlaying and rebuilding - in the pppd config we write

require-mppe
mppe-optional

and observe the normal operation of vpn with and without client-side encryption enabled.

already compiled packages for debian lenny (maybe they are suitable for ubuntu) I can upload it on request

Source: https://habr.com/ru/post/56496/


All Articles