Does VyOS support L2TP with Public IP over the tunnel (like pfSense does with CoreTransit)?

Hey folks,

I’ve been playing around with CoreTransit’s Static IP Anywhere service, and I’m currently using it with pfSense to get a public IP through an L2TP tunnel. It works great, basically, pfSense connects via L2TP, authenticates with CoreTransit, and I get a routed public IP on my WAN side over the tunnel.
I wrote up how I got it working here if anyone’s curious:

Now I’m trying to move this setup over to VyOS, but I can’t find much info on whether VyOS supports this same kind of L2TP client configuration, especially where you actually receive the public IP via the tunnel interface (not just create an L2TP server or client for VPN access).
For reference, CoreTransit provides:

  • Authenticated tunnels

  • Custom IP allocations

  • 100 Mbps standard (upgradable to 1 Gbps)

  • IPv4 and IPv6

  • Optional BGP support

  • Works well for Starlink, LTE, and CG-NAT setups

They also have a Cisco config example here:

So my question is:
Has anyone managed to get VyOS to connect to CoreTransit (or a similar provider) via L2TP and actually pull a public IP over the tunnel?

1 Like

The Core Transit IP Anywhere service looks pretty cool. I wish they had locations in Canada.

But for your question, why do you want to use L2TP? They also support WireGuard which seems like a much better option.

I’m currently use Wireguard but I also have an L2TP plan that is very affordable before they increased the priced.

There is no native L2TPv2 client, feature request T1229

You can start in a container, whatever you want.

I’ve done this with A&A’s L2TP service using a container on VyOS. I haven’t made it public but I could if folks would find it useful.

1 Like

I’d really appreciate it, and any instructions on how you set it up and got it running would be great as well.

Ok try this - GitHub - fransking/vyos-l2tpclient: l2tp client container for VyOS. I’m not suggesting this is in anyway best practice but it works for my use case.

3 Likes

I may need to revisit this later; I’m not quite following it at the moment. Thanks for adding it to Git!

Hey Fransking,

I follow these steps and it appears nothing errored out but nothing is showing me that the tunnel is connected.

you should be able to see any log output by running

show container log l2tpclient

Also what does

ifconfig pppaa

output

admin-jharrison712@ESC-ONP-DELL-TRBR-1:/config$ show container log l2tpclient
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 systemd[1]: Starting VyOS Container l2tpclient…
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 podman[3980]: time=“2025-10-31T14:41:56Z” level=warning msg=“The input device is not a TTY. The --tty and --interactive flags might not work properly”
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 podman[3980]: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 podman[3980]: f56d68a4dbcaa5d394c7daa1a382846cb08f4eb3a19d04d124815fe6868bcfde
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 systemd[1]: Started VyOS Container l2tpclient.
Oct 31 14:41:56 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: Starting client
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Not looking for kernel SAref support.
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Using l2tp kernel support.
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: xl2tpd version xl2tpd-1.3.18 started on ESC-ONP-DELL-TRBR-1 PID:1
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Forked by Scott Balmos and David Stipp, (C) 2001
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Inherited by Jeff McAdams, (C) 2002
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Forked again by Xelerance (www.xelerance.com) (C) 2006-2016
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Listening on IP address 0.0.0.0, port 1701
Oct 31 14:41:57 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connecting to host peering1.dfw1.coretransit.io, port 1701
Oct 31 14:42:28 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Maximum retries exceeded for tunnel 5987. Closing.
Oct 31 14:42:28 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connection 0 closed to 216.146.16.1, port 1701 (Timeout)
Oct 31 14:42:59 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Unable to deliver closing message for tunnel 5987. Destroying anyway.
Oct 31 14:42:59 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Will redial in 15 seconds
Oct 31 14:43:14 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connecting to host peering1.dfw1.coretransit.io, port 1701
Oct 31 14:43:45 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Maximum retries exceeded for tunnel 58019. Closing.
Oct 31 14:43:45 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connection 0 closed to 216.146.16.1, port 1701 (Timeout)
Oct 31 14:44:16 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Unable to deliver closing message for tunnel 58019. Destroying anyway.
Oct 31 14:44:16 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Will redial in 15 seconds
Oct 31 14:44:31 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connecting to host peering1.dfw1.coretransit.io, port 1701
Oct 31 14:45:02 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Maximum retries exceeded for tunnel 37084. Closing.
Oct 31 14:45:02 ESC-ONP-DELL-TRBR-1 l2tpclient[3994]: xl2tpd[1]: Connection 0 closed to 216.146.16.1, port 1701 (Timeout)
admin-jharrison712@ESC-ONP-DELL-TRBR-1:/config$ ifconfig pppaa
pppaa: error fetching interface information: Device not found
admin-jharrison712@ESC-ONP-DELL-TRBR-1:/config$ ifconfig pppaa output
output: No address associated with name
ifconfig: `–help’ gives usage information.

admin-jharrison712@ESC-ONP-DELL-TRBR-1:~$ dig peering1.dfw1.coretransit.io

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> peering1.dfw1.coretransit.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 720
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;peering1.dfw1.coretransit.io. IN A

;; ANSWER SECTION:
peering1.dfw1.coretransit.io. 300 IN A 216.146.16.1

;; Query time: 74 msec
;; SERVER: 9.9.9.9#53(9.9.9.9) (UDP)
;; WHEN: Fri Oct 31 14:04:35 UTC 2025
;; MSG SIZE rcvd: 73

admin-jharrison712@ESC-ONP-DELL-TRBR-1:~$ nc -vzu peering1.dfw1.coretransit.io 1701
Connection to peering1.dfw1.coretransit.io (216.146.16.1) 1701 port [udp/l2f] succeeded!
admin-jharrison712@ESC-ONP-DELL-TRBR-1:~$ podman logs l2tpclient --tail 100

216.146.16.1, port 1701 (Timeout)
Oct 31 14:42:59 ESC-ONP-DELL-TRBR-1

this looks to me like core transit has their l2tp server listening on a different port

Or you need some options from Linux xl2tpd L2TP Client Configuration - Core Transit LLC that I’m not setting in the container.

does anything stand out?

Not seeing a specific port in the pfSense configuration.

This is the output from a fresh VyOS rolling 1.5 install connecting ok to core transit (atlanta)

Nov 02 10:49:42 ct-fw1-local systemd[1]: Starting VyOS Container l2tpclient…
Nov 02 10:49:42 ct-fw1-local podman[4154]: time=“2025-11-02T10:49:42Z” level=warning msg=“The input device is not a TTY. The --tty and --interactive flags might not work properly”
Nov 02 10:49:42 ct-fw1-local podman[4154]: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: Starting client
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Not looking for kernel SAref support.
Nov 02 10:49:43 ct-fw1-local podman[4154]: 527f925010e85449f781ebdf4a7ea8fd39915c7b6432e04a545f4a52a5367b6a
Nov 02 10:49:43 ct-fw1-local systemd[1]: Started VyOS Container l2tpclient.
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Using l2tp kernel support.
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: xl2tpd version xl2tpd-1.3.18 started on ct-fw1-local PID:1
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Forked by Scott Balmos and David Stipp, (C) 2001
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Inherited by Jeff McAdams, (C) 2002
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Forked again by Xelerance (``www.xelerance.com``) (C) 2006-2016
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Listening on IP address 0.0.0.0, port 1701
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Connecting to host ``peering1.atl1.coretransit.io``, port 1701
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Connection established to 134.199.56.1, 1701. Local: 36117, Remote: 48867 (ref=0/0).
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Calling on tunnel 36117
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: Call established with 134.199.56.1, Local: 32783, Remote: 53658, Serial: 1 (ref=0/0)
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: start_pppd: I’m running:
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “/usr/sbin/pppd”
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “plugin”
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “pppol2tp.so”
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “pppol2tp”
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “7”
Nov 02 10:49:43 ct-fw1-local l2tpclient[4167]: xl2tpd[1]: “passive”

Is your VyOS router sitting behind pfsense and/or already connected to core transit? Is it possible you are filtering packets on udp port 1701?

Hey Fransking,

I think I forgot to disable the HA for L2TP on the second pfSense, I dd it on the first one but I can still ping the public IP that is downstream so I think second node took over. Let me re-try it, also in your A&A’s L2TP are you doing a /29 or etc downstream as well?

Hmm that didn’t work either here is my running config, I’m not using IPv6 at all.

container {
name l2tpclient {
allow-host-networks
capability net-admin
device ppp {
destination /dev/ppp
source /dev/ppp
}
environment L2TP_IFDOWN_COMMAND {
value pppaa-down.sh
}
environment L2TP_IFNAME {
value pppaa
}
environment L2TP_IFUP_COMMAND {
value pppaa-up.sh
}
environment L2TP_PASSWORD {
value -redacted-
}
environment L2TP_SERVER {
value peering1.dfw1.coretransit.io
}
environment L2TP_USERNAME {
value -redacted-
}
image fransking/vyos-l2tpclient:latest
volume l2tpclient {
destination /config/l2tpclient
source /config/l2tpclient
}
volume modules {
destination /lib/modules
source /lib/modules
}
volume pppaa-ifdown {
destination /sbin/pppaa-down.sh
source /config/scripts/pppaa-down.sh
}
volume pppaa-ifup {
destination /sbin/pppaa-up.sh
source /config/scripts/pppaa-up.sh
}
}
}
interfaces {
ethernet eth0 {
address 192.168.4.2/28
description “Uplink to UDM”
hw-id 00:26:b9:87:53:b4
offload {
gro
gso
sg
tso
}
}
ethernet eth1 {
address 192.168.10.1/24
description LAN
hw-id 00:26:b9:87:53:b5
offload {
gro
gso
sg
tso
}
}
ethernet eth2 {
address -redacted-/29
description “CoreTransit Gateway Downstream”
hw-id 00:10:18:6b:d4:58
mtu 1420
offload {
gro
gso
sg
tso
}
}
ethernet eth3 {
hw-id 00:10:18:6b:d4:5a
offload {
gro
gso
sg
tso
}
}
loopback lo {
}
wireguard wg0 {
address -redacted-/31
description “CoreTransit WireGuard Tunnel”
mtu 1420
peer hDqmR4VF {
address 134.199.56.1
allowed-ips 0.0.0.0/0
description “CoreTransit Peer”
persistent-keepalive 10
port 10253
public-key ****************
}
port 51820
private-key ****************
}
}
nat {
source {
rule 5020 {
description “masquerade for PPPAA”
outbound-interface {
name pppaa
}
translation {
address masquerade
}
}
}
}
policy {
}
protocols {
static {
route 0.0.0.0/1 {
next-hop 134.199.56.108 {
}
}
route 128.0.0.0/1 {
next-hop 134.199.56.108 {
}
}
route 134.199.56.1/32 {
next-hop 192.168.4.1 {
}
}
route 192.168.1.0/24 {
next-hop 192.168.4.1 {
}
}
}
}
service {
ntp {
allow-client {
address 127.0.0.0/8
address 169.254.0.0/16
address 10.0.0.0/8
address 172.16.0.0/12
address 192.168.0.0/16
address ::1/128
address fe80::/10
address fc00::/7
}
server 0.us.pool.ntp.org {
}
server time1.vyos.net {
}
server time2.vyos.net {
}
server time3.vyos.net {
}
}
snmp {
community -redacted- {
}
contact “-redacted-”
location -redacted-
}
ssh {
listen-address 192.168.4.2
port 22
}
}
system {
config-management {
commit-revisions 100
}
console {
device ttyS0 {
speed 115200
}
}
domain-name -redacted-
host-name -redacted-
login {
user -redacted- {
authentication {
encrypted-password ****************
principal principal
}
}
}
}
name-server 9.9.9.9
name-server 1.1.1.1
option {
reboot-on-upgrade-failure 5
}
sysctl {
parameter net.core.default_qdisc {
value fq
}
parameter net.ipv4.tcp_congestion_control {
value bbr
}
}
syslog {
local {
facility all {
level info
}
facility local7 {
level debug
}
}
}
time-zone Etc/UTC
}
vpn {
}

Hey @fransking So I got it to work if I do a fresh install, however seems like I can’t run WG and L2TP together on different interfaces

That’s good. Might be a core transit thing if they see you connected to them over WireGuard already or could be that the WireGuard connection is altering the routing table such that L2TP packets are going over this tunnel rather than clearnet.

Seems like its 0.0.0.0/0 for the WG interface that is trying to break it. In what section do I need to set to route the public IP to another interface like eth7