katalix / go-l2tp

Go library for building L2TP applications on Linux systems
MIT License
43 stars 15 forks source link

L2TPv3 dynamic tunnels #1

Open DerZade opened 3 years ago

DerZade commented 3 years ago

This is my first time working with L2TP and I was really happy to find a well document library. I need dynamic L2TPv3 tunnels for my use case (as far as I know at least :D) and I stumbled upon the following error:

https://github.com/katalix/go-l2tp/blob/570d7630dcaa4e03836d03edbd899e14da11a042/l2tp/l2tp_dynamic_tunnel.go#L557

Why exactly does this library not support dynamic L2TPv3 tunnels? Is this hard to achieve, because it is complex to implement or is it just a lot of work but relatively easy to implement and therefore doable for a L2TP noob like me? :)

If the latter applies, I would think about opening a PR, because my life would be a lot simpler, if this library would cover my use case.

NeutraleNull commented 3 years ago

What is the status on this? I would love dynamic v3 tunnels as well.

dfawcus commented 3 years ago

The reason is almost certainly that L2TPv3 is a different RFC (3931) to L2TPv2 (2661), with different message formats, and it is only the latter which this library currently supports. Both specs and L2F share a similar basic framing format (L2F using version 1) such that they can be distinguished when operating on the same port, but they are not interoperable (except in downgrading at start up).

As I recall there are also some subtle differences in how tunnels and session interrelate between the two specs. L2TPv2 only offers transport of PPP sessions, L2TPv3 offers transport of many forms of pseudo-wire. RFC 3931 states:

1.1. Changes from RFC 2661

Many of the protocol constructs described in this document are carried over from RFC 2661. Changes include clarifications based on years of interoperability and deployment experience as well as modifications to either improve protocol operation or provide a clearer separation from PPP. The intent of these modifications is to achieve a healthy balance between code reuse, interoperability experience, and a directed evolution of L2TP as it is applied to new tasks.

Notable differences between L2TPv2 and L2TPv3 include the following:

Separation of all PPP-related AVPs, references, etc., including a portion of the L2TP data header that was specific to the needs of PPP. The PPP-specific constructs are described in a companion document.

Transition from a 16-bit Session ID and Tunnel ID to a 32-bit Session ID and Control Connection ID, respectively.

Extension of the Tunnel Authentication mechanism to cover the entire control message rather than just a portion of certain messages.

Details of these changes and a recommendation for transitioning to L2TPv3 are discussed in Section 4.7.

So I guess the reason this only does RFC 2661 is that (outside of telco's), it is the most common case. Being used for Microsoft Windows L2TP/IPsec as part of their RAS stuff. Also I believe that L2TPv2 is what many ADSL deployment use, having been in place for a while. It possibly also only implements the logic for the LAC role, not the LNS role.

The authors had to start somewhere, so it does make a degree of sense starting with L2TP(v2) - even if only due to being able test against the MS client and server.

It also allows them to test against the various other clients and servers (e.g. on Linux, macOS, etc) which were previously created to interoperate with the MS products.

DerZade commented 3 years ago

At least according to the README v3 (RFC3931) is supported. Only dynamic v3 tunnels don't seem to be supported. It doesn't look like there is a lot of interested in that being implemented considering this issues is months old now.

dfawcus commented 3 years ago

That rather depends upon the meaning for 'supported' and the programs in question.

A quick glance at the code reveals that most of the L2TPv3 AVPs are recognised - e.g. 62 'Pseudowire Capabilities List' is currently unimplemented. So that layer is almost complete. I'm not sure how complete the corresponding tests are.

The message layer looks to have support for both forms of base header. I'd guess it does not have complete support for v3 control messages, as some comments and code suggests those are place holders. However extending that bit should be obvious. Similarly the tests could maybe do with enhancements.

Similarly I'm guessing from a quick glance that the two dynamic layers (tunnel and session) only have complete support for v2, as there again seem to be obvious hints as to where v3 is not supported.

The transport layer (reliable control session) looks like it will support both versions.

There are places where code has the possibility of handling direct encap over IP, which is a v3 only option. An interesting question arises about the FSM for controlling the dynamic sessions - I have a vague recollection that this differs between v2 and v3.

So in summary, I'd suggest that the README is quite honest, and you're possibly inferring more than it intended to state. The code needs enhancing for full dynamic v3 support, but it does look as if it is significant step on that road.

So after half an hour glancing at the code, I'd say that for someone interested, capable and willing to do the work, it is a reasonable base upon which to build that facility.

dfawcus commented 3 years ago

It possibly helps that I had read this:

https://katalix.com/blog/announcing-go-l2tp.html

DerZade commented 3 years ago

Thanks a lot for the clarification ❤️

tomparkin commented 1 year ago

Hi @DerZade and apologies for not responding to this issue sooner! It seems my github notifications are broken :-(

Thanks for your interest in this library.

As @dfawcus says, there's really no fundamental reason go-l2tp doesn't support dynamic L2TPv3 tunnels/sessions; it's just that the control protocol for L2TPv3, described by RFC3931, is quite different to the L2TPv2 protocol and we haven't gotten around to implementing the former yet.

Furthermore, most client-side usecases for L2TP I know of tend to be either for ADSL connections or for VPN, and both tend to use L2TPv2, so we considered that would probably be the most useful thing for go-l2tp to support first.