PPP HOWTO: PPPoE for DSL and fiber, and PPP over serial today
PPP (the Point-to-Point Protocol) is still how many DSL and fiber providers hand out connections: your router or Linux box runs PPP over Ethernet (PPPoE) and logs in with a user name and password. This page shows how to do that with NetworkManager or plain pppd, how to deal with VLAN tags and the smaller MTU, and how to run PPP over a serial line.
The classic PPP-HOWTO (modem dial-up, kernel 2.2) and the ADSL and DSL HOWTOs are kept by the Linux Documentation Project; the PPP-HOWTO is at tldp.org. This page replaces them for current systems.
How PPPoE works
PPPoE (RFC 2516) has two stages. In discovery, your machine broadcasts a PADI packet on the Ethernet link; the provider's access concentrators answer with PADO; your machine picks one with PADR and gets a session number in PADS. In the session stage, ordinary PPP runs inside Ethernet frames: it authenticates you (PAP or CHAP), then IPCP and IPv6CP hand out addresses. Either side ends the session with PADT.
The PPPoE header takes 6 bytes and the PPP protocol field 2 more, so the largest IP packet is 1500 − 6 − 2 = 1492 bytes. That number matters, as you will see below.
What you need from the provider
- User name and password (often
name@provider). - Whether a VLAN tag is needed on the WAN link, and which number. Many fiber and VDSL services need one; your provider's support pages or router settings say which.
- Whether IPv6 is offered over the same session (usually by DHCPv6 prefix delegation after PPP comes up).
- Which Ethernet port faces the ONT or DSL modem (run
ip linkto see the names, for exampleenp1s0).
Your DSL modem or ONT must be in "bridge" mode, so that it passes PPPoE through instead of dialing itself.
PPPoE with NetworkManager
On desktops and most servers that use NetworkManager, one command creates the profile. Without a VLAN:
sudo nmcli connection add type pppoe con-name wan ifname enp1s0 \
pppoe.username 'name@provider' pppoe.password 'secret'
sudo nmcli connection up wan
With a VLAN tag (here VLAN 7 — use your provider's number), create the VLAN interface first and run PPPoE on top of it with pppoe.parent:
sudo nmcli connection add type vlan con-name wan-vlan ifname enp1s0.7 dev enp1s0 id 7 \
ipv4.method disabled ipv6.method disabled
sudo nmcli connection add type pppoe con-name wan ifname ppp0 pppoe.parent enp1s0.7 \
pppoe.username 'name@provider' pppoe.password 'secret'
sudo nmcli connection up wan
Leave pppoe.service empty unless the provider gives you a service name. To detect a dead line faster, set ppp.lcp-echo-interval 20 and ppp.lcp-echo-failure 3 (the second only works together with the first). Check the result:
nmcli device status
ip addr show ppp0
ip route # default route via ppp0
journalctl -b | grep -i pppd
NetworkManager starts pppd with its own plugin, so the logs say pppd even though you never wrote a pppd configuration.
PPPoE with pppd directly
On a router or minimal server without NetworkManager, use pppd from the ppp package (as of November 2026: 2.5.2 in Debian 13 and Ubuntu 26.04, 2.4.9 in Ubuntu 24.04; the latest upstream release is 2.5.5). PPPoE support is a plugin built into the package, pppoe.so; releases before 2.4.9 called it rp-pppoe.so. It uses the kernel's PPPoE driver, so no separate user-space daemon is needed.
First check that the provider answers at all. pppoe-discovery sends PADI and lists the access concentrators that reply, without starting a session:
sudo ip link set enp1s0 up
sudo pppoe-discovery -I enp1s0
Create the peer file /etc/ppp/peers/wan:
plugin pppoe.so
nic-enp1s0
user "name@provider"
noauth
hide-password
defaultroute
replacedefaultroute
usepeerdns
+ipv6
persist
maxfail 0
holdoff 10
lcp-echo-interval 20
lcp-echo-failure 3
mtu 1492
mru 1492
noipdefault
For a VLAN, create the VLAN interface (sudo ip link add link enp1s0 name enp1s0.7 type vlan id 7, then sudo ip link set enp1s0.7 up, and make it permanent in your network configuration) and use nic-enp1s0.7.
Put the password in /etc/ppp/chap-secrets and /etc/ppp/pap-secrets, because you do not know in advance which method the provider will choose. The fields are client, server, secret and allowed addresses:
# client server secret IP addresses
"name@provider" * "secret" *
sudo chmod 600 /etc/ppp/chap-secrets /etc/ppp/pap-secrets
Start it in the foreground the first time, with debugging, so you see every step:
sudo pppd call wan nodetach debug
When it works, stop it with Ctrl-C and start it in the background with sudo pppd call wan. On Debian and Ubuntu, sudo pon wan and sudo poff wan do the same, and plog shows the last log lines. To start at boot on Debian, add a stanza to /etc/network/interfaces (auto wan, iface wan inet ppp, provider wan) or write a small systemd unit that runs /usr/sbin/pppd call wan nodetach.
About the route options: defaultroute adds a default route through the peer only if none exists yet; replacedefaultroute lets it replace an existing one. usepeerdns asks for up to two DNS servers and writes them to /etc/ppp/resolv.conf; with systemd-resolved, hook them in from a script in /etc/ppp/ip-up.d/ or set DNS servers yourself.
The MTU problem and MSS clamping
Hosts on your LAN use an MTU of 1500. When they open a TCP connection through a 1492-byte PPPoE link, large packets must be fragmented or rejected, and if ICMP "fragmentation needed" messages are filtered somewhere, connections hang: the page starts loading and then stalls. The standard fix on the router is to clamp the TCP maximum segment size to the route MTU. In nftables, in the forward chain of your firewall:
table inet filter {
chain forward {
type filter hook forward priority filter; policy accept;
oifname "ppp0" tcp flags syn tcp option maxseg size set rt mtu
}
}
Merge the rule into your existing ruleset rather than loading this table on its own with a policy you did not plan; see the Firewall HOWTO. If your provider supports RFC 4638 and your Ethernet path carries frames slightly larger than normal, you can negotiate a 1500-byte PPP MTU instead, but 1492 always works.
PPP over a serial link
PPP still connects two machines over a null-modem cable, a radio modem or an out-of-band console line. On the first machine:
sudo pppd /dev/ttyS0 115200 10.0.0.1:10.0.0.2 crtscts local lock noauth nodetach
And on the second machine, the addresses reversed:
sudo pppd /dev/ttyS0 115200 10.0.0.2:10.0.0.1 crtscts local lock noauth nodetach
local ignores the modem control lines (there is no carrier on a plain cable), crtscts turns on hardware flow control (leave it out if your cable lacks RTS/CTS), and lock creates a lock file so no other program opens the port. Use noauth only on a cable you control; on anything reachable by others, set require-chap and a secret in chap-secrets. For dial-up through a modem, add connect "/usr/sbin/chat -v -f /etc/chatscripts/dialup" and use the modem's device; see the Modem HOWTO.
Troubleshooting
- No PADO / "Timeout waiting for PADO packets"
- Nothing answers the discovery broadcast. Check the cable and the interface name, that the modem or ONT is in bridge mode, and the VLAN number.
pppoe-discoveryis the quickest test. - Authentication failed
- Wrong user name or password, or the secret is in only one of the two secrets files. Look for "PAP authentication failed" or "CHAP authentication failed" in the log.
- Connected, but no Internet
- Check
ip route: if another default route already existed and you did not usereplacedefaultroute, traffic still goes the old way. Then check DNS. - Some web sites hang, others work
- The MTU problem. Add MSS clamping on the router.
- Link drops after some hours
- Many providers force a reconnect daily.
persistandmaxfail 0(or NetworkManager's autoconnect) bring it back; the LCP echo options detect a dead link.
Where to look: pppd logs to syslog with facility daemon, so journalctl -b -t pppd or journalctl -b | grep pppd shows the whole negotiation when debug is set. To share the connection with your LAN, continue with the IP Masquerade HOWTO.
Sources
- pppd(8) including PPPoE options, Debian 13 (ppp 2.5.2)
- pppoe-discovery(8), Debian 13
- pon, poff and plog(1), Debian 13
- chat(8), Debian 13
- Point-to-Point Protocol project (ppp 2.5.5 release)
- ppp NEWS: rp-pppoe plugin renamed to pppoe in 2.4.9
- ppp package in Ubuntu 24.04 and in Ubuntu 26.04
- nm-settings-nmcli(5): pppoe and ppp settings, Debian 13
- RP-PPPoE client, relay and server
- RFC 2516: A Method for Transmitting PPP Over Ethernet (PPPoE)
- RFC 4638: Accommodating a Maximum Transit Unit/Maximum Receive Unit Greater Than 1492 in PPPoE
- Mangling packet headers (TCP MSS), nftables wiki
- Linux PPP HOWTO (classic), Linux Documentation Project