[pptp-server] Hack to force MPPE encryption from the server side

Nathan Meyers nmeyers at javalinux.net
Tue Dec 28 14:10:05 CST 1999


When I was looking recently for a way for PoPToP to force PPTP clients
to use MPPE encryption, it appeared to be impossible - outside the
bounds of PPP to force a compression choice on the client.

I've developed a hack that gets the job done without too much ugliness.
It's a small sentry, written in perl, that detects whan an unencrypted
PPTP connection has been established, and kills it. If anyone's
interested, here's what I did:

1) Hacked pptpd to run /usr/sbin/pppd.mppe_sentry instead of
/usr/sbin/pppd as the PPP daemon.

2) Implemented /usr/sbin/pppd.mppe_sentry in perl (see below).

It works by sitting between pptpd and pppd, and monitoring the log
output from pppd. It looks for two things in the log output:

- The message announcing the "remote IP" connection

- The message announcing the use of MPPE encryption, which may occur
before or shortly after the "remote IP" message.

If it doesn't see the MPPE message within 10 seconds of seeing the
"remote IP" message, it kills pppd. Crude, but effective.



A possible alternate implementation would be to:

1) Don't hack pptpd

2) Rename /usr/sbin/pppd to /usr/sbin/pppd.real

3) Install the script as /usr/sbin/pppd, changing line 14 to run
/usr/sbin/pppd.real

Unfortunately, this approach involves the sentry whenever pppd is used
for anything, not just PPTP connections - which won't work in my
environment.


Perl source for the sentry is attached below.


Nathan Meyers
nmeyers at javalinux.net



#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-12-28 12:06 PST by <nathanm at vectra>.
# Source directory was `/home/nathanm/VPN'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    716 -rwxr-xr-x pppd.mppe_sentry
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh14010; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= pppd.mppe_sentry ==============
if test -f 'pppd.mppe_sentry' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pppd.mppe_sentry' '(file already exists)'
else
  $echo 'x -' extracting 'pppd.mppe_sentry' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pppd.mppe_sentry' &&
#!/usr/bin/perl
X
$^F = 20;
pipe(FROMPPPD, TOSENTRY) || die "Failed to open pipe";
X
$pid = fork;
if ($pid == -1) { die "fork() failed"; }
X
if ($pid == 0)
{
X    # Child... run pppd
X    close(FROMPPPD);
X    open(STDOUT, '>&TOSENTRY');
X    unshift @ARGV, "/usr/sbin/pppd";
X    exec(@ARGV) || die "Failed to execute pppd";
}
X
close(TOSENTRY);
X
$encryption = 0;
while (<FROMPPPD>)
{
X    chomp;
X    if (/MPPE/) { $encryption = 1; }
X    if (/remote IP/ && !$encryption)
X    {
X       # We've seen the "remote IP" message but no sign of encryption.
X       # Give pppd 10 seconds to report encryption or the dog dies
X       $SIG{ALRM} = 'check_encrypt';
X       alarm 10;
X    }
}
X
sub check_encrypt
{
X    if (!$encryption) { kill SIGTERM, pid; }
}
SHAR_EOF
  $shar_touch -am 1225114399 'pppd.mppe_sentry' &&
  chmod 0755 'pppd.mppe_sentry' ||
  $echo 'restore of' 'pppd.mppe_sentry' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null;
then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pppd.mppe_sentry:' 'MD5 check failed'
21d20f3cc32b233450f52c0402f59386  pppd.mppe_sentry
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pppd.mppe_sentry'`"
    test 716 -eq "$shar_count" ||
    $echo 'pppd.mppe_sentry:' 'original size' '716,' 'current size'
"$shar_count!"
  fi
fi
rm -fr _sh14010
exit 0




More information about the pptp-server mailing list