[Swan-dev] leftsubnet's virtual specifier [long!]
D. Hugh Redelmeier
hugh at mimosa.com
Sun May 26 19:02:41 UTC 2019
First, let me admit that I don't understand this stuff. So when I say
something, there's a good chance that I've got it wrong.
Here is what ipsec.conf(5) says:
================
[in a conn]
leftsubnet
private subnet behind the left participant, expressed as
network/netmask (actually, any form acceptable to
ipsec_ttosubnet(3)); Currently, IPv4 and IPv6 ranges are
supported. if omitted, essentially assumed to be left/32,
signifying that the left end of the connection goes to the
left participant only
It supports two magic shorthands vhost: and vnet:, which can
list subnets in the same syntax as virtual-private. The value
%priv expands to the networks specified in virtual-private.
The value %no means no subnet. A common use for allowing
roadwarriors to come in on public IPs or via accepted NATed
networks from RFC1918 is to use leftsubnet=vhost:%no,%priv.
The vnet: option can be used to allow RFC1918 subnets without
hardcoding them. When using vnet the connection will
instantiate, allowing for multiple tunnels with different
subnets.
overlapip
a boolean (yes/no) that determines, when *subnet=vhost: is
used, if the virtual IP claimed by this states created from
this connection can with states created from other
connections.
Note that connection instances created by the Opportunistic
Encryption or PKIX (x.509) instantiation system are distinct
internally. They will inherit this policy bit.
The default is no.
This feature is only available with kernel drivers that
support SAs to overlapping conns. At present only the (klips)
mast protocol stack supports this feature.
[in config setup]
virtual-private
contains the networks that are allowed as subnet= for the
remote clients when using the vhost: or vnet: keywords in the
subnet= parameters. In other words, the address ranges that
may live behind a NAT router through which a client connects.
This value is usually set to all the RFC-1918 address space,
excluding the space used in the local subnet behind the NAT
(An IP address cannot live at two places at once). IPv4
address ranges are denoted as %v4:a.b.c.d/mm and IPv6 is
denoted as %v6:aaaa::bbbb:cccc:dddd:eeee/mm. One can exclude
subnets by using the !. For example, if the VPN server is
giving access to 192.168.1.0/24, this option should be set
to:
virtual-private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!192.168.1.0/24.
This parameter is only needed on the server side and not on
the client side that resides behind the NAT router, as the
client will just use its IP address for the inner IP setting.
This parameter may eventually become per-connection. See also
leftsubnet=
Note: It seems that T-Mobile in the US and Rogers/Fido in
Canada have started using 25.0.0.0/8 as their pre-NAT range.
This range technically belongs to the Defence Interoperable
Network Services Authority (DINSA), an agency of the Ministry
of Defence of the United Kingdom. The network range seems to
not have been announced for decades, which is probably why
these organisations "borrowed" this range. To support
roadwarriors on these 3G networks, you might have to add it
to the virtual-private= line.
[in BUGS]
Multiple L2TP clients behind the same NAT router, and multiple
L2TP clients behind different NAT routers using the same Virtual
IP is currently only working for the KLIPSNG stack.
================
The description of leftusbnet= should be broken down into more
paragraphs. The ideas need to be separated better.
====
>From the description of leftsubnet=
The vnet: option can be used to allow RFC1918 subnets without
hardcoding them.
Surely this describes %priv, not vnet:. And only if vitual-private=
hasn't overridden this setting.
This error is repeated in the description of virtual-private=.
====
The description of virtual-private= does not say that it defaults to
the RFC1918 subnets. But it is kind of suggested. Is this the
default?
====
>From the description of overlapip=
a boolean (yes/no) that determines, when *subnet=vhost: is
used, if the virtual IP claimed by this states created from
this connection can with states created from other
connections.
I cannot parse this English.
I think that "virtual IP" should be "virtual subnet".
I suspect that "states" is the wrong word in both instances.
I think that the word overlap is missing.
====
in the description of virtual-private=, the example is too wide for a
man page.
The note should perhaps be moved to BUGS.
====
check_virtual_net_allowed() is only called in IKEv1 code. Does that
mean that anything goes in IKEv2?
====
The true syntax of virtual-private= allows the %v4: and %v6: prefixes
to be dropped. In that case, the IP version is inferred from the
text.
====
Contrary to the documentation, the list of subnets in the virtual
specification of leftsubnet= is not the same as in virtual-private=.
The latter allows "!" (to denote exclusion) and the former does not.
====
The implemented syntax of leftsubnet= virtual options is:
{vhost,vnet}:[methods [, method]* ]
where method is any of:
%no (meaning no virtual IP (accept IP of host/32))
%priv (meaning accept system-wide private net list)
[%v4:]x (meaning accept literal IPv4 subnet x)
[%v6]:x (meaning accept literal IPv6 subnet x)
%all (meaning accept all IPs [only for testing])
These methods can be combined arbitrarily, but perhaps not
meaningfully. The code in check_virtual_net combines them in ways
that might well be accidental.
Should they be combine as an "or"/"union" or an "and"/"intersection"?
Obviously, all uses of literal IP subnets are united: any is accepted.
All uses of %no in our tree seem to be vhost:%priv,%no. Should all
other uses be prohibited? Should it be simplified to a single token?
That should make the description more clear.
%all should perhaps override everything else. Maybe it should be
considered a bug to combine it.
%priv, %v4, and %v6 could make sense to combine with union or
intersection. Currently it is union.
What the code of check_virtual_net_allowed does, in this order:
- if vhost: if proposed subnet is not a /32: fail
- if %no: if proposed subnet is a /32 and it contains (is) host
address, succeed
- if %priv and is included in the good list of virtual-private and
isn't included in the bad list, succeed. Otherwise, remember
tentative failure.
- if there was a list of subnets in the virtual part, and the proposed
was in it, succeed. Otherwise, remember tentative failure
- if %all, succeed
- if there was a tentative failure, fail
- succeed.
That's complicated to comprehend!
I think that %no should fail if it doesn't succeed. In other words,
it should constrain the proposed subnet to exactly the host, with no subsequent
escape clauses. In other words, I'd change its rule to:
- if %no: if proposed subnet is not a /32 or it does not contain
(isn't) host address, fail
This is kind of an "and"/"intersection" instead of the current
"or"/"union"
%all overrides %priv and any explicit list of IPs. Perhaps it should
not be allowed to appear with them.
More information about the Swan-dev
mailing list