When two devices establish a point-to-point connection — over a dial-up modem, DSL line, or PPP-based VPN — they often need to authenticate each other before allowing traffic to flow. Two of the oldest and most widely supported authentication protocols for this are PAP (Password Authentication Protocol) and CHAP (Challenge Handshake Authentication Protocol), both defined for use with PPP (Point-to-Point Protocol). This article explains how each works, their security tradeoffs, and how to configure both on Linux.
What Is PPP?
PPP is a Layer 2 protocol used to establish a direct connection between two nodes — historically over serial lines, modems, and ISDN, and still used today for DSL (PPPoE) and some VPN types. PPP handles link establishment, authentication, and network-layer configuration (like assigning an IP address) before user data starts flowing.
graph LR
A[Client / Dial-up Device] -->|PPP Link| B[NAS / ISP Router]
B -->|Authenticate: PAP or CHAP| A
B -->|Assign IP, Establish Session| APAP: Password Authentication Protocol
PAP is the simpler of the two. The client sends a username and password in clear text to the server, which either accepts or rejects the connection.
Client Server
|---- Username + Password -->|
|<----- Accept / Reject -----|
Why PAP Is Weak
Because credentials are sent in plaintext, anyone capturing the traffic (e.g., with a packet sniffer on a shared line) can see the password directly. PAP also only authenticates once, at connection setup — there’s no ongoing verification during the session. It should only be used when a more secure protocol isn’t supported by the far end, or over a link that is already encrypted at another layer.
CHAP: Challenge Handshake Authentication Protocol
CHAP is more secure. It uses a three-way handshake with a challenge-response mechanism based on a shared secret, and it never sends the password itself over the wire.
sequenceDiagram
participant C as Client
participant S as Server
S->>C: Challenge (random value)
C->>S: Response = MD5(ID + Secret + Challenge)
S->>S: Computes its own expected response
S->>C: Success / Failure- After the link is established, the server sends a challenge — a randomly generated value.
- The client combines the challenge, a session ID, and the shared secret, hashes them (traditionally with MD5), and sends back the response.
- The server performs the identical calculation using its own copy of the secret and compares results.
- Because the actual secret is never transmitted, and the challenge changes every time, CHAP is resistant to replay attacks and plaintext sniffing — an eavesdropper only ever sees the hash of a different challenge each time.
CHAP can also re-challenge periodically during a session, providing ongoing verification that PAP cannot offer.
PAP vs CHAP Comparison
| Feature | PAP | CHAP |
|---|---|---|
| Credential transmission | Plaintext | Never transmitted; hash-based challenge-response |
| Handshake | 2-way | 3-way |
| Replay attack resistance | None | Yes (random challenge each time) |
| Re-authentication during session | No | Yes, supported |
| Complexity | Simple | Moderate |
| Security | Weak | Stronger (though still MD5-based, considered legacy today) |
| Use case | Legacy/compatibility only | Preferred over PAP wherever supported |
Configuring PPP with CHAP and PAP on Linux
Linux uses the pppd daemon along with chat scripts (for dial-up) or pppoe tools (for DSL) to establish PPP sessions. Authentication secrets are stored in two files:
/etc/ppp/pap-secrets/etc/ppp/chap-secrets
Step 1: Install PPP Tools
sudo apt update
sudo apt install ppp pppconfig pppoeconf
Step 2: Configure CHAP Secrets
Edit /etc/ppp/chap-secrets:
# client server secret IP addresses
myusername * MySecretPass123 *
- client: the identity your machine presents
- server:
*means accept from any server, or specify the server’s peer name - secret: the shared secret used in the hash calculation
- IP addresses: optional restriction on allowed IPs
Set correct permissions, since this file contains a secret:
sudo chmod 600 /etc/ppp/chap-secrets
Step 3: Configure PAP Secrets (if required)
Edit /etc/ppp/pap-secrets using the same format:
myusername * MySecretPass123 *
Step 4: Create a PPP Peer Configuration
Create /etc/ppp/peers/mylink:
/dev/ttyS0
115200
crtscts
noauth
defaultroute
user "myusername"
remotename myisp
persist
To force a specific authentication method, add:
refuse-pap
require-chap
This tells pppd to only accept CHAP and explicitly refuse PAP — a good security practice when the far end supports CHAP.
Step 5: Bring Up the Link
sudo pon mylink
sudo plog # view the connection log
sudo poff mylink # bring the link down
Step 6: Verify the Interface
ip addr show ppp0
ip route showConfiguring PPPoE (DSL) with CHAP
For DSL connections using PPPoE, pppoeconf automates much of this setup:
sudo pppoeconfIt will prompt for your Ethernet interface, ISP username and password, and automatically populate /etc/ppp/chap-secrets and /etc/ppp/pap-secrets.
CHAP/PAP on Cisco Devices (for context)
Since CHAP/PAP is also heavily used on Cisco routers for WAN links, here’s an equivalent configuration for comparison:
Router(config)# username ISP-Router password MySecretPass123
Router(config)# interface Serial0/0/0
Router(config-if)# encapsulation ppp
Router(config-if)# ppp authentication chapTo require CHAP but fall back to PAP if the peer doesn’t support it:
Router(config-if)# ppp authentication chap papBest Practices
- Prefer CHAP over PAP whenever both ends support it.
- Never reuse the same secret across multiple links — treat
chap-secretsandpap-secretslike any other credential store. - Restrict file permissions on secrets files to
600, owned by root. - Where possible, use a more modern authentication method (like EAP with PPP, or IPsec/IKEv2 for VPNs) instead of legacy CHAP/PAP, especially for anything internet-facing.
- Rotate shared secrets periodically, particularly after staff turnover on business links.
- Monitor
/var/log/syslogorplogoutput for repeated authentication failures, which can indicate misconfiguration or an attack.
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Link comes up but authentication fails | Mismatched secret or username | Verify entries in chap-secrets/pap-secrets match exactly (case-sensitive) |
| “Peer refused to authenticate” | Peer doesn’t support the requested method | Check require-chap/refuse-pap settings, adjust as needed |
| No PPP session starts at all | Serial/DSL modem issue, wrong device path | Check /dev/ttyS0 or PPPoE interface with dmesg |
| Works with PAP but not CHAP | Secret mismatch or hostname mismatch | Confirm the “server” field in chap-secrets matches the peer’s advertised name |
Use sudo pppd debug combined with sudo tail -f /var/log/syslog for verbose, real-time visibility into the negotiation process.
Further Reading
- RFC 1334 — PPP Authentication Protocols (PAP)
- RFC 1994 — PPP Challenge Handshake Authentication Protocol (CHAP)
- Linux
pppdman page - Cisco: Configuring PPP Authentication
- Ubuntu PPPoE Documentation
Conclusion
CHAP and PAP represent two very different philosophies toward the same problem — one prioritizing simplicity, the other prioritizing security. While both are considered legacy by modern standards, they remain in active use across DSL and dial-up infrastructure, and understanding their mechanics gives valuable insight into how challenge-response authentication works more broadly across networking.