Setting up a PPTP VPN on CentOS 9 can be useful for legacy compatibility or quick internal use, but it’s important to understand the security trade-offs: PPTP is considered weak by modern cryptographic standards and should generally be avoided for sensitive traffic. If you must deploy PPTP (for example, to support an old client) this guide walks you through a practical, step‑by‑step configuration on CentOS 9 with detailed commands, firewall and NAT considerations, authentication, and troubleshooting tips.

Prerequisites and security considerations

Before you begin, ensure you have:

  • Root or sudo access to a CentOS 9 server with a public IP.
  • Basic familiarity with systemd, firewall configuration (firewalld or nftables), and networking concepts.
  • Backups or snapshots in case you need to roll back network changes.

Security note: PPTP uses MSCHAPv2 and MPPE which have known weaknesses. For production environments and sensitive data, prefer OpenVPN, WireGuard, or IPsec. If you proceed, restrict access to trusted clients, use strong passwords, and consider additional layers like per-user firewall rules or client certificates via another VPN.

Overview of the installation process

The main steps covered in this article:

  • Install and enable the PPTP daemon (pptpd).
  • Configure server options and authentication (chap-secrets).
  • Enable IP forwarding and set up NAT for VPN clients.
  • Adjust firewall rules (firewalld or nftables) and SELinux considerations.
  • Validate and troubleshoot the VPN connection.

Step 1 — Install pptpd and required packages

On CentOS 9, pptpd is not provided in the default repositories. You can enable EPEL (Extra Packages for Enterprise Linux) and then install. As root or with sudo, run:

sudo dnf install epel-release -y

sudo dnf install pptpd ppp -y

These packages include pptpd (daemon) and ppp (pppd) for authentication and routing. Confirm installation with: rpm -qa | grep pptpd

Kernel modules

PPTP relies on PPP kernel modules. Load them if not present: sudo modprobe ppp_generic ppp_mppe ppp_async ppp_deflate. Check: lsmod | grep ppp

Step 2 — Configure /etc/pptpd.conf and /etc/ppp/options.pptpd

Edit /etc/pptpd.conf to define local and remote IP pools. A minimal configuration:

localip 10.0.0.1

remoteip 10.0.0.100-10.0.0.200

Adjust ranges to fit your network plan; the server IP (localip) is the VPN gateway for clients.

Next, edit /etc/ppp/options.pptpd. Key options:

name pptpd

require-mschap-v2

ms-dns 8.8.8.8

ms-dns 8.8.4.4

mru 1400

mtu 1400

Use require-mschap-v2 to insist on MSCHAPv2. The ms-dns lines provide DNS to clients. Consider internal DNS if you have internal resources.

Step 3 — Configure user authentication (chap-secrets)

Add user credentials to /etc/ppp/chap-secrets. Each line follows: username server password allowed_IPs. Example:

vpnuser pptpd StrongP@ssw0rd 10.0.0.101

To allow the user to receive any address from the pool, set the last field to * or leave it blank depending on client needs. Use strong passwords and minimize user list. For more secure authentication, consider integrating with RADIUS or LDAP instead of local files.

Step 4 — Enable IP forwarding and adjust sysctl

PPTP clients will need routing access to other networks. Enable IPv4 forwarding persistently:

echo “net.ipv4.ip_forward = 1” >> /etc/sysctl.conf

sysctl -p

If you want granular control, you can set net.ipv4.conf.all.rp_filter = 0 or tune other networking sysctls, but avoid weakening global protections unless necessary.

Step 5 — Configure NAT (iptables or nftables / firewalld)

Most CentOS 9 systems use nftables or firewalld by default. Below are methods for both. Ensure you choose the one your system uses.

Firewalld

If using firewalld, you can add a masquerade to the public zone and open TCP/1723 and GRE (protocol 47):

sudo firewall-cmd –permanent –add-service=pptp

sudo firewall-cmd –permanent –add-masquerade

sudo firewall-cmd –reload

Note: The default “pptp” service opens TCP/1723. GRE is a protocol, handled by the kernel; firewalld supports it implicitly for the pptp service. Verify with firewall-cmd –list-all.

nftables / manual iptables-nft

If you manage rules directly with nftables, add NAT POSTROUTING for the network range:

sudo nft add table ip nat

sudo nft ‘add chain ip nat POSTROUTING { type nat hook postrouting priority 100; }’

sudo nft add rule ip nat POSTROUTING ip saddr 10.0.0.0/24 oifname “eth0” masquerade

Replace eth0 with your external interface and 10.0.0.0/24 with your remoteip range. Also allow TCP/1723 and GRE in the filter table.

Step 6 — Start and enable pptpd service

Enable and start the service with systemd:

sudo systemctl enable –now pptpd

Check service status: sudo systemctl status pptpd

Examine logs for startup errors: sudo journalctl -u pptpd -f

Step 7 — Client configuration and testing

On a Windows client, create a new VPN connection, choose PPTP, set the server address to your server’s public IP, and supply credentials from /etc/ppp/chap-secrets. On Linux, you can use NetworkManager or the pppd client.

Verify the client receives an IP from the remoteip range and can ping the gateway (10.0.0.1). From the server, check active ppp interfaces: ip a | grep ppp

Use tcpdump to inspect GRE and PPP negotiation: sudo tcpdump -n -i eth0 host and proto gre

Troubleshooting checklist

If the client fails to connect or cannot route traffic, work through:

  • Confirm pptpd is listening: ss -ltnp | grep 1723
  • Check kernel modules: lsmod | grep ppp
  • Review logs: journalctl -u pptpd and /var/log/messages or /var/log/secure for PPP authentication entries.
  • Ensure MSCHAPv2 is negotiated. If you see authentication falls back to MSCHAPv1 or PAP, verify /etc/ppp/options.pptpd contains require-mschap-v2 and the client supports it.
  • If GRE packets are blocked upstream (cloud providers, routers), likely TCP/1723 opens but GRE is dropped; contact your provider or adjust upstream firewall.
  • Verify NAT rule applies to the VPN subnet and outbound interface. Use nft list ruleset or firewall-cmd –list-all.

Log snippets to look for

Successful authentication lines will show pppd: pppd[PID]: CHAP authentication succeeded. Failure modes often show pppd: pppd[PID]: CHAP authentication failed for ‘user’.

Advanced tips and hardening

  • Use strong per-user passwords and consider time-limited accounts.
  • Restrict PPTP access via firewall to specific client IP ranges if possible.
  • Monitor authentication logs and set up alerts for repeated failures.
  • Consider using RADIUS for centralized authentication and accounting.
  • If you must use PPTP for compatibility, pair it with application-level encryption (TLS/HTTPS) for sensitive services.

SELinux

By default, PPTP doesn’t generally require SELinux changes. If you encounter denials, check audit logs: sudo ausearch -m avc -ts recent. Create targeted policies rather than disabling SELinux.

Migration path away from PPTP

Given the security limitations of PPTP, plan a migration to a modern VPN technology. WireGuard offers high performance and a small codebase; OpenVPN and strongSwan/IPsec provide mature alternatives with richer authentication options. If you need client compatibility, consider maintaining PPTP for legacy devices on an isolated gateway while moving primary traffic to higher-security VPNs.

Following these steps, you should have a functional PPTP VPN on CentOS 9 with authentication, NAT, and firewall rules. Always balance operational necessity against security risk and plan to migrate away from PPTP when feasible.

For more guides, configuration examples, and VPN recommendations, visit Dedicated-IP-VPN: https://dedicated-ip-vpn.com/