A PPTP profile that insists on encryption usually fails in the same place: PPP agrees on an authentication exchange that never produces the key material MPPE needs. The tunnel looks half alive, the password is accepted, and the link drops before any traffic crosses it. Reaching for the CHAP dropdown until something connects hides the real defect, which is a contract between the authentication method and the protection policy. The checks below are ordered so that each one rules out a cheaper cause than the next.

Two negotiations run inside one PPTP connection

PPTP carries a normal PPP session inside a GRE tunnel, and the two negotiate separately. The outer layer decides how packets are encapsulated and which control channel exists; the inner PPP session decides who the peer is and what protection rides on top. A password prompt therefore proves something about the inner layer only, and a completed outer handshake proves nothing about either. Profiles fail here because people debug the tunnel while the disagreement sits inside PPP.

Plain CHAP is the challenge-response exchange in RFC 1994, built on a shared secret and nothing else. MS-CHAPv2 is a different exchange with different messages and a different output, standardised in RFC 2759. The shared word in the two names is the only thing they have in common on the wire. Neither name tells you what the exchange produces, which is the only part that matters.

That is why an option labelled simply CHAP is ambiguous in a legacy profile. When the server wants MS-CHAPv2 and the client offers plain CHAP, link control can still complete and a password can still be accepted. The failure arrives later, when the server tries to derive protection keys from an exchange that produced none.

Match the required method to the keys it can produce

MPPE keys are not a property of PPP in general. For the Microsoft CHAP family the derivation is specified in RFC 3079, and it takes as input the output of an MS-CHAP exchange rather than a shared secret. EAP methods reach the same place by a different route, with the authentication server returning the keys as MS-MPPE-Recv-Key and MS-MPPE-Send-Key attributes. Plain CHAP appears in neither path, which is the whole reason the mismatch exists.

A configuration that requires MPPE while refusing every method able to supply keys is internally contradictory. pppd resolves that contradiction by refusing the link, not by inventing keys, so the visible result is a session that authenticates and then terminates during the network phase. Retrying the client will not change that while the server refuses the only methods that derive anything.

The rule that follows is short: if the profile requires MPPE, the method must be an MS-CHAP variant or an EAP method whose keys the server returns. Refusing only MS-CHAPv2 does not enforce that, because MS-CHAPv1 also derives keys and stays available unless it is refused separately; refusing both leaves plain CHAP and PAP, which derive nothing and make the requirement unsatisfiable. Name the accepted method explicitly instead of listing the ones you dislike. Dropping the encryption requirement to make a client connect is a downgrade, not a repair.

Read the server's options before editing a client

Most of these mismatches are visible on the server in two files, and reading them costs less than rebuilding a client. On a Linux PPTP endpoint the relevant settings live in the pppd options file that pptpd passes through. Run it on the server, not from a client status screen. Start with the lines that require, refuse or name a protection mode:

sudo grep -nE 'require-|refuse-|mppe|mschap' /etc/ppp/options.pptpd

Read the output as a contract rather than a list of flags. A line that requires MPPE while refusing both MS-CHAP variants cannot be satisfied by any client, and a missing requirement for an MS-CHAP method leaves the door open to exchanges that yield no keys. Then check who may authenticate at all, which the secrets file decides:

sudo sed -n '1,20p' /etc/ppp/chap-secrets
sudo pppd --version

Write down three values before changing anything: the outer protocol, the authentication method the server requires, and whether protection is mandatory or optional. Those three determine every later decision, and guessing them from a client dialog is how a profile ends up half configured. Keep the file open while you work, because the next section needs the same three values.

Locate the failure by PPP phase

PPP reports failures in phases, and the phase tells you which clause of the contract broke. A link that never leaves link control has an encapsulation or negotiation problem, while one that authenticates and then dies is usually a policy or key problem. A link that stays up and carries nothing has moved on to routing, which is a different investigation.

The journal keeps the phase lines, and they are more useful than a higher debug level. Ask for the PPP processes and the protection messages, then read the authentication result before anything else. The last lines usually name the clause that refused:

sudo journalctl -b --no-pager | grep -iE 'pppd|pptpd|mppe|chap' | tail -40

In that output, look for the authentication result first and then for a complaint that protection was required but not negotiated. The second message is the signature of the contradiction above, and no amount of retrying clears it while the server refuses the only method that can produce keys. Two traps are worth naming: raising the debug level without reading the phase lines produces noise, and capturing challenge material or passwords turns a configuration task into a credential leak. Record that phase before changing any option.

Plan the exit before the old endpoint is switched off

MPPE is a historical link protection mechanism, and its presence does not make PPTP a sensible choice for a new deployment. Current Microsoft guidance already advises against PPTP and against L2TP/IPsec with a pre-shared key for new remote access rollouts. Keeping a legacy endpoint alive is a decision about an existing service, not a template for the next one.

When the endpoint has to stay, write the contract down: outer protocol, required authentication method, mandatory protection, and the client version that negotiates it. When it can go, choose the replacement's gateway identity, its client authentication and where the credentials will live before touching the old profile. Then plan routes, DNS and the resources each user is authorized to reach. Validate the intended client against the owner's requirements rather than against a working connection.

A deliberate rejection should stay a rejection, because falling back to an unprotected mode to make a test pass converts a policy failure into an exposure. The finished state is a supported, documented contract, not the smallest set of changes that makes one old connection succeed. Leave the legacy profile in place, unused and documented, until the replacement passes the same checks.

អត្ថបទពាក់ព័ន្ធ