ppp icon indicating copy to clipboard operation
ppp copied to clipboard

pre-up, auth and script issues

Open jkroonza opened this issue 3 years ago • 2 comments

Hi All,

The description for ip-pre-up in the man page states:

              A program or script which is executed just before  the  ppp  network  interface  is
              brought  up.   It is executed with the same parameters as the ip-up script (below).
              At this point the interface exists and has IP addresses assigned but is still down.
              This  can  be used to add firewall rules before any IP traffic can pass through the
              interface.  Pppd will wait for this script to finish before bringing the  interface
              up, so this script should run quickly.

With +ipv6 the statement that it is "execute just before the ppp network interface is brought up" is false. On average. I'm assuming that the statement was never true with +ipx, and MPLSCP doesn't really help the situation either.

We've made numerous tests now, most of the external scripts aren't waited for, so concurrency causes further issues, so working through the various scripts, in an approximate execution order, considering the UP sequence only (and listing the lcp-{up,down} too in #342 and ipv6-pre-up in #341):

lcp-up - waited for, iface is down.  No auth details yet.  With PR #342.
auth-up - not waited for (interface is still down at start-of-execution).

From here on any of the following blocks can execute in parallel. Up to here no IP information is available. For IPv4:

ip-pre-up - waited for, supposedly interface is down, however IPV6CP could in theory already have brought up interface.
ip-up - not waited for, interface is guaranteed up.

For IPv6:

ipv6-pre-up - waited for, supposedly interface is down, however, IPCP could in theory already have brought up the interface (PR #341).
ipv6-up - not waited for.

So only one pre-up script will execute at a time. auth-up could still be executing.

When the first pre-up executes, only IP information for that specific protocol will be available (ie, if ipv6-pre-up executes first, ipv4 information will be missing, and vice versa).

Using auth-up isn't feasible since the interface could come up during execution, so adding firewalling from here is probably not the right solution either.

lcp-up executes prior to auth, so auth information isn't available. Assuming that other information COULD be available, and we don't need auth information or IP information we could make adjustments at this stage, we could also in theory take certain actions here, and then later fine-tune in ip{,v6}-up.

Assuming that the first execution of *-pre-up is used to make firewalling, at least here we can use AUTH information, but we must only act on the first invocation, which means we cannot rely on IP information at this stage.

The only currently workable solutions I can see:

If auth information is not required: make updates in lcp-up. If auth-information is required, action from auth-up, but somehow blok the *-pre-up scripts until auth has completed (locking is problematic since in theory *-pre-up could be fired up quickly enough so that even if the first thing auth-up does is take a lock *-pre-up could execute first), so use the first run of *-pre-up to make these adjustments (assuming IPCP and IPV6CP are the only two inner protocols, no MPLSCP nor IPX or any others). Alternatively, adjust pppd so that auth-up will block (optionally a confirmation setting?).

I'm not sure the issue of having all information for all protocols available prior to interface up is feasible. Especially since as I understand inner protocols could change over time, eg, at connection start IPCP could be brought up, and then later IPV6CP could also be enabled. I'm not sure there are any implementations where this is the case.

I'm not sure what the best approach here is, from what I can tell there are a few possible "solutions" to various aspects of the problem:

  1. Execute *-pre-up with parameters of what the IP information WILL BE, prior to configuring it. Make no guarantee regarding the if state. For on-demand *-pre-up will still be executed multiple times in theory.
  2. Wait for auth-up.

So for *-pre-up, before adding the addresses to the ppp interface, execute pre-up, passing the IP information, but not yet configured. But I'm not sure that would actually prevent problems.

Waiting for auth-up means we can make adjustements for firewalls etc, even for protocols that may or may not come up (just assume they will, or set it up in a "not allowed" state, and then adjust from *-up as needed).

Happy to action the code, just need to get some input on the best approaches here. Currently our "default" firewalling pretty much does set up into the "not allowed" state, but there are other system changes that we are looking to also make, where we do need the authenticated information, prior to establishing IP*CP.

jkroonza avatar May 17 '22 07:05 jkroonza

Typically firewall developers have been using a match on interface with a wildcard. For example,

iptables -i ppp+ ..., 
iptables -o ppp+

Would you be able to work around the problem with a more generic way to match the rules and interfaces?

Also, IP information will not be available until IPCP or IPV6CP has reached state UP. So if you are trying to indeed match on an assigned IP-address before the interface are configured. You are still going to have a race-condition.

Doing so in or just after the LCP layer (and before Auth) is come up, then you won't have the IP information. Doing it before Auth, you won't even know if this is a valid connection.

You able to better help my understanding of your issue here?

enaess avatar May 31 '22 15:05 enaess

Hi,

We have multiple sources of where ppp+ comes from, so ppp+ doesn't quite get us there. Also, different users have different firewalling policies applied. So we don't need the IP information, but we do need the authentication information in order to either add the interface into.

During ip-pre-up IP information is available, and without ipv6 the interface is guaranteed to still be down. We don't generally use the IP information at this stage, but we do set up shaping here prior to the interface moving into an UP state, but not if ipv6 comes up first. So PR #341 adds ipv6-pre-up (only the first of these two executions will have the interface still DOWN), both waits and so we have information mechanisms that carries info between the scripts that allows us to determine whether or not further action is required (so first -pre-up sets up shaping for example).

During lcp-down we tear down shaping again. This could go into ${proto}-down scripts, but it makes sense to have a common script for this that's guaranteed to only execute once (else we need even more comms between -down scripts).

During lcp-up we also initialize the messaging system (including ensuring there is no remnant data from a previous session for this unit) used between the scripts so we don't need a valid connection at this stage, we just need something that runs really early during the initialization process. We also ensure that the general ip:interface:username map we keep up to date is properly reset so that incorrect data won't cause a connection being brought up to be torn down prematurely (to facilitate CoA processing from the radius servers locally, ie, freeradius on port 3799 locally, processes some stuff and then takes action). This same information is again reset in lcp-down.

I trust this motivates it. I reckon we can close this issue here and just continue on the individual PRs rather.

jkroonza avatar Jun 01 '22 15:06 jkroonza

#367 relates, the discussion of which is more comprehensive, I'm thus going to close this from my side.

jkroonza avatar Jan 04 '23 08:01 jkroonza