VPNs remain one of the most practical ways to secure access to internal services such as private Git repositories. L2TP over IPsec is a widely supported VPN option that provides compatibility across Windows, macOS, and Linux clients while leveraging IPsec for encryption. This article walks you through a robust, step-by-step L2TP/IPsec setup for securing Git access, with detailed configuration examples, firewall rules, client instructions, and hardening tips aimed at site administrators, development teams, and ops engineers.

Why use L2TP/IPsec for Git access?

Before diving into configuration, understand the rationale:

  • Compatibility: Native support in mainstream OSes (Windows, macOS) and easy-to-install clients for Linux.
  • Network-level isolation: VPN places clients on a private subnet, allowing Git servers to bind to private IPs and avoid public exposure.
  • Encryption: IPsec provides strong confidentiality and integrity for traffic between client and server.
  • Access control: You can combine VPN authentication with SSH keys for layered security on Git.

Overview of the architecture

The typical deployment involves one Linux-based VPN gateway (public IP) running an IPsec daemon (strongSwan/libreswan) and an L2TP daemon (xl2tpd). The gateway provides a VPN subnet (e.g., 10.10.10.0/24). Git servers (or a single Git host) are placed on an internal network or reachable from the VPN gateway. Clients connect to the gateway and access the Git host via its internal IP or internal DNS name.

Prerequisites

  • Linux server (Ubuntu/Debian/CentOS) with a public IPv4 address.
  • Root or sudo access.
  • Installed packages: strongSwan (or libreswan), xl2tpd, ppp.
  • Firewall control (iptables or nftables) and ability to change sysctl settings.
  • Private Git host configured for SSH (recommended) or HTTPS.

Server-side setup (Ubuntu/Debian example)

Install required packages

Install strongSwan, xl2tpd, and ppp:

sudo apt update && sudo apt install strongswan xl2tpd ppp -y

IPsec configuration (/etc/ipsec.conf)

Create a minimal config geared for L2TP (IKEv1). Adjust names and IPs as needed.


config setup
uniqueids=never

conn L2TP-PSK
authby=secret
pfs=no
auto=add
keyingtries=3
rekey=no
type=transport
left=%defaultroute
leftprotoport=17/1701
right=%any
rightprotoport=17/%any
ike=aes256-sha1-modp1024
esp=aes256-sha1

IPsec PSK (/etc/ipsec.secrets)

Use a strong pre-shared key (PSK). Store as root-only. Example:

YOUR.SERVER.IP.ADDR : PSK "VeryStr0ngPreSharedKeyHere!"

xl2tpd configuration (/etc/xl2tpd/xl2tpd.conf)

Configure the LNS section:


[global] port = 1701

[lac vpn-connection] lns = YOUR.SERVER.IP.ADDR
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

PPP options (/etc/ppp/options.xl2tpd)

Configure PPP parameters, DNS, and IP range assignment:


require-mschap-v2
ms-dns 10.10.10.1
auth
mtu 1400
mru 1400
nodefaultroute
lock
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4

Client authentication (/etc/ppp/chap-secrets)

Define VPN username/password pairs (tab-separated):

client server secret IP addresses

gituser lns Str0ngUserP@ss *

Enable IP forwarding and sysctl tuning

Enable forwarding so VPN clients can reach internal hosts:

sudo sysctl -w net.ipv4.ip_forward=1

Persist in /etc/sysctl.conf or /etc/sysctl.d/99-sysctl.conf:

net.ipv4.ip_forward=1

Firewall rules (iptables example)

Open IPsec/L2TP ports and NAT VPN subnet to internal network if necessary:

Allow IPsec and L2TP

sudo iptables -A INPUT -p udp --dport 500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 1701 -j ACCEPT

Allow ESP

sudo iptables -A INPUT -p 50 -j ACCEPT

NAT outgoing VPN client traffic to internal network (if Git host is on a different subnet)

sudo iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE

Allow forwarding between VPN and internal interface

sudo iptables -A FORWARD -s 10.10.10.0/24 -d 192.168.1.0/24 -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Replace eth0 and internal network blocks with your actual interfaces and subnets.

Start services

Restart strongSwan and xl2tpd and confirm status:


sudo systemctl restart strongswan
sudo systemctl restart xl2tpd
sudo systemctl enable strongswan xl2tpd

Client configuration

Clients will connect using the public IP, PSK, and username/password defined earlier. Below are common OS configurations.

Windows (built-in L2TP)

  • Create a new VPN connection (Settings → Network & Internet → VPN).
  • Server name: your.server.ip.addr
  • VPN type: L2TP/IPsec with pre-shared key. Enter the PSK in advanced options.
  • Use the VPN username/password defined in chap-secrets.
  • In the connection properties → Security → Allow these protocols → Uncheck EAP if using username/password; choose MS-CHAP v2.

macOS

  • System Preferences → Network → + → Interface: VPN → L2TP over IPsec.
  • Server address: your.server.ip.addr. Account name: gituser. Click Authentication Settings → enter password and the shared secret.
  • Advanced: send all traffic over VPN if you need full tunnel; otherwise configure split tunnel via routing on the client.

Linux (NetworkManager-l2tp)

Install the plugin and configure via GUI or nmcli:

sudo apt install network-manager-l2tp network-manager-l2tp-gnome

Create a VPN entry, specifying the server, PSK, username, and password; enable MSCHAP-v2 and disable EAP if necessary.

Configure Git server for VPN-only access

After clients can reach the VPN subnet, lock down your Git host to accept connections only from the VPN.

Option A — Bind SSH to the private interface

Edit /etc/ssh/sshd_config and set ListenAddress to the internal interface IP (e.g., 192.168.1.10) or the VPN gateway NAT’d address. Restart sshd. This prevents SSH from listening on the public interface.

Option B — Firewall restriction

Keep SSH listening on all interfaces but add firewall rules on the Git host to only allow SSH connections from the VPN subnet:

sudo iptables -A INPUT -p tcp -s 10.10.10.0/24 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP

Git over HTTPS

If you use HTTPS for Git, ensure the web server or Git service is reachable on an internal IP and that TLS certificates are valid for the internal hostname or use an internal CA trusted by clients.

Testing and validation

  • Confirm VPN connection: ping the VPN gateway (10.10.10.1) and internal Git server IP.
  • Verify SSH: ssh git@192.168.1.10 should connect only when VPN is up.
  • Clone a repo: git clone git@192.168.1.10:repos/myrepo.git
  • Use tcpdump or tshark on the VPN gateway to inspect L2TP/IPsec packets if troubleshooting: sudo tcpdump -i eth0 host your.client.ip

Security best practices and hardening

  • Prefer certificates over PSKs: PSKs are convenient but single point of compromise. Consider IPsec with strongSwan using X.509 client certificates for authentication.
  • Use strong cryptographic suites: Use AES-256 and SHA-2-based algorithms when possible and avoid weak Diffie-Hellman groups (use modp2048 or stronger).
  • Limit VPN privileges: Apply firewall rules so VPN clients can only access Git services and essential infrastructure, not the whole LAN.
  • Layered auth: Require SSH key-based authentication on the Git server in addition to VPN login.
  • Monitor and rate-limit: Use fail2ban and host-based IDS to detect brute-force attempts and anomalous behavior.
  • Rotate credentials: Change PSKs and user passwords periodically and remove unused accounts from /etc/ppp/chap-secrets and authorized_keys.
  • Use split tunneling carefully: Only route Git-related networks through the VPN if you need minimal exposure; full tunneling is safer for unknown client networks.

Troubleshooting common issues

Below are quick diagnostics:

  • Connection fails to establish: check /var/log/syslog, /var/log/auth.log, and strongSwan logs for IKE negotiation errors. Common issues: incorrect PSK, NAT traversal problems, or blocked UDP/4500/500.
  • PPP session terminates immediately: verify chap-secrets credentials and that ppp options allow MSCHAP-v2.
  • No routing to Git server: verify net.ipv4.ip_forward is enabled on the gateway and that iptables FORWARD rules permit traffic.
  • DNS not resolving internal hostnames: set MS-DNS in options.xl2tpd or configure the client to use your internal DNS server.

In environments where you need the most modern security and simpler configuration, also evaluate WireGuard or IKEv2-based setups. However, L2TP/IPsec remains a pragmatic option for mixed-OS fleets that leverage built-in client support.

By placing your Git services behind a VPN, you dramatically reduce the attack surface and centralize access control. Follow the detailed configuration and hardening guidance above to deploy a resilient L2TP/IPsec gateway, restrict Git access to internal IPs, and enforce layered authentication for production-grade security.

For more detailed tutorials and configuration templates tailored to different Linux distributions and enterprise scenarios, visit Dedicated-IP-VPN at https://dedicated-ip-vpn.com/.