Force a jail to use OpenVPN tunnel

spork

Active Member

Reaction score: 14
Messages: 163

So I have a few questions about how to best do this... I have an OpenVPN client on a host and I would like a jail on that host to use that tunnel for all non-local access. I also need to reach this jail from other hosts on the same subnet. The host/jail are behind a firewall, so no firewalling or NAT are happening on the host.

I found this post describing a way to do this, and in theory, this basically works:

https://blog.feld.me/posts/2015/06/routing-a-freebsd-jail-through-openvpn/

What I'm struggling with here though is that the above config relies on setting a static IP in jail.conf. The provider at the other end of my VPN allocates that IP dynamically. The current jail.conf configuration style does not seem to allow the "ineherit" option for an IP address, nor offer a way to limit "inherit" to a particular interface (in this case tun0).

Are there any workarounds here to replicate the "inherit" behavior? It's the only way I can see to deal with an interface whose address may change without restarting the jail...

Any other ideas? I've seen people mention running OpenVPN inside a jail, I suspect using "VIMAGE", but I'm not certain whether VIMAGE is currently stable or production-ready.
 

Chris_H

Daemon

Reaction score: 216
Messages: 1,076

OK spork I know exactly how to do this. This is often how I setup my jail(8)s (minus vpn). But that's incidental. Before I explain how I do it. I see you indicated you use ezjail, in another thread. Is this ezjail, of a conventional jail?

--Chris
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

Using "jail.conf" method here, first time I'm actually playing around with that before I attempt it at work.
 

Chris_H

Daemon

Reaction score: 216
Messages: 1,076

Using "jail.conf" method here, first time I'm actually playing around with that before I attempt it at work.
Good for you, spork ! Good choice. :)
OK then
Basically, you're just going to clone your loopback device, and route your traffic through lo1
You'll also want (need) to use pf(4).
Here goes:
rc.conf(5)
Code:
pf_enable="YES"
pflog_enable="YES"

cloned_interfaces="lo1"

jail_enable="YES"

jail_list="<your_jail_name_here>"

jail.conf(5):
Code:
your-jail-name {
path = /path/to/your/jail;
host.hostname = your-jail-name.localhost;
ip4.addr = 127.0.0.2;
interface = lo1;
#jid = 1;
exec.clean;
mount.devfs;
mount.fdescfs;
mount.procfs;
exec.start =    "/bin/sh /etc/rc";
exec.stop = "/bin/sh    /etc/rc.shutdown";
exec.consolelog = /var/log/jail.your-jail-name.console.log;
}
pf.conf(5):
Code:
EXT_ADDR="<your-internet-IP-here>"

...

set skip on { lo0 }

...

nat pass on <your-nic-device-name-here> from lo1 to any -> $EXT_ADDR
rdr pass on <your-nic-device-name-here> proto tcp from any to lo1 -> $EXT_ADDR

That is the basics of it.

HTH

--Chris
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

Hmmm... I don't think that's going to help with my situation. What I really need is to figure out how to get the jail() "inherit" value set.

From the manpage:

Code:
   ip4       Control the availability of IPv4 addresses.  Possible values are
             ``inherit'' to allow unrestricted access to all system addresses,
             ``new'' to restrict addresses via ip4.addr, and ``disable'' to
             stop the jail from using IPv4 entirely.  Setting the ip4.addr
             parameter implies a value of ``new''.

Basically, I need to get "tun0" inside the jail AND allow for a dynamic IP on that interface.

Also, this host is not a firewall, it's a host behind a firewall, so there is no "external" address - it's just a server on my LAN and the VPN instance is running not on the firewall, but on this server (OpenVPN only needs a single UDP or TCP port to work, unlike IPSEC, so running it inside the LAN is easy/uncomplicated).

This is the current jail.conf:

Code:
[spork@media ~]$ cat !$
cat /etc/jail.conf
# shared settings
exec.start += "sleep  2 ";
allow.raw_sockets = 1;
exec.clean;
exec.system_user = "root";
exec.jail_user = "root";
exec.start += "/bin/sh /etc/rc";
exec.stop = "";
mount.devfs;
mount.fstab = "/etc/fstab.$name";
mount.fdescfs;
allow.mount;
allow.set_hostname = 1;

private {
    exec.fib = 1;
    host.hostname = "private.example.com";
    ip4.addr += "10.9.0.8"; # TUN0 IP/VPN
    ip4.addr += "10.3.2.9"; # LOCAL LAN
    path = "/jails/private.example.com";
    mount +=  "procfs /jails/private.example.com/proc procfs rw 0 0";
    exec.consolelog = "/var/log/jail_priv_console.log";
}

The jail is on it's own FIB so it can have a default route out the tun0 device instead of the LAN.

OpenVPN is started in the jail, also on it's own FIB:

setfib -F 1 /usr/local/sbin/openvpn-client /usr/local/etc/openvpn/mullard.conf


This all works... Until I need to reconnect the VPN. At that point I have to put a new IP in jail.conf and restart the jail. I need something that doesn't require manual intervention. I do have the jail protected at the firewall - any traffic from "10.3.2.9" can't reach the internet, so the jail does lose connectivity when the VPN goes down (this is a requirement, obviously - I don't want to ever send traffic out of this jail other than via the VPN).
 

ShelLuser

Son of Beastie

Reaction score: 2,146
Messages: 3,802

Chris_H solution is pretty on the mark. I think you're overestimating what you can do with a Jail.

To put this very simple: a jail cannot set up any networking configurations on its own. If you look at that same jail(8) manualpage you'll notice that the use of the ip4 setting is tied into ip4.addr, I quote: "A list of IPv4 addresses assigned to the jail.". Because that's the only way a jail works: stuff gets assigned to it.

You won't be able to "just" mount media from inside a jail unless it has been granted on the host. You won't be able to "just" use networking inside a jail (think about ICMP) unless you set this up on the host, and so on.

And dynamic IP addresses inside a jail also won't work: it'll be the host that sets all of that up.

As such it's actually a good idea to set up your jail on a local loopback device, then set up your VPN on the host after which you can use a firewall such as pf to forward incoming data onto the jail.
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

I think it is possible, it's in the manpage, and Mark Feld (see link in first post) is doing this, just with a prior version where jail.conf had a bit more flexibility. I'll give it a shot with the old rc.conf jail code I guess.
 

ShelLuser

Son of Beastie

Reaction score: 2,146
Messages: 3,802

I think it is possible, it's in the manpage
Nothing in the manualpage states that jails can act as a DHCP client. Why do you think ip4.addr and ip6.addr exist?

As to that blog you linked to: please note the static IPv4 address which got assigned to the jail through use of ip4.addr. And just because someone on a random blog states that you could use a certain option doesn't automatically make that true.

Instead, if you do some research on people who have been here before you'll notice the exact same suggestion which Chris_H mentioned earlier. See for example this post on the mailinglist or this forum thread.

A jail gets IP addresses assigned to it and has no control over that process, because that's restricted to the host. This is simply the (somewhat restricted) way in which jails work.
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

The jail manpage was quoted above. Note the "inherit" option.

There's no DHCP involved here, this is a VPN connection using the "tun0" interface. The host doesn't even route any traffic over that interface. This is an entirely different scenario from either of the posts your quoting.

They are getting routable IPs via DHCP on the host and then NAT'ing that to the jail. That is not what I'm doing.

If I were to try to narrow this down to the simplest question, it would be "how do I get the ip4 'inherit' flag set via jail.conf?" (as noted in the jail manpage quoted above)
 

Chris_H

Daemon

Reaction score: 216
Messages: 1,076

Hey spork ! :)
You're almost there. Really. :)
If I were you, I take a good long look at pf.conf(5). You can do it, and I'm cheering for you.
If I had a clearer picture of what you're really trying to do. I'd probably be of more assistance. But I'd need better details. :)
Really, pf(4) is your friend here, and will get you to your desired destination. :)

--Chris
EDIT
pf is just as much routing as it is "firewall". Don't let the fact that it's often called, and used as "firewall" mislead you. After all, isn't filtering, just another name for routing?
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

D'oh!

"ip4.addr=inherit" is NOT the same as "ip4=inherit"

That works ("works" here meaning I can change the tun0 IP at will and it still works), and the jail is basically unrestricted as far as networking goes. Sadly I can't, for example allow ONLY tun0 in the jail.

What I'm really trying to do? :) Have a jail that only has access to the internet via a VPN (not a corporate VPN, VPN as in Mullard, NordVPN, PIA, etc.).

The NAT option I think assumes that I am OK with the host having OpenVPN running in the same FIB, and I'm not. The intersection of pf and FIBs is a bit scary, so I'm trying to avoid that.

I have a few paths to try:

Just use VIMAGE for the jail (why is VIMAGE still not in GENERIC for 11.2???). This seems well-supported and there are a ton of HOWTOs on that since FreeNAS uses iocage/VIMAGE jails. For example: https://forums.freenas.org/index.ph...-a-jail-so-it-only-connects-to-the-vpn.18669/

Use a normal jail, pretty much where I started with this post, but add some commands to the vpn up/down script to run "jail -m new_vpn_ip,local_lan_ip", which should allow the jail to keep running, but adjust for any VPN IP changes. This seems easier...
 

Chris_H

Daemon

Reaction score: 216
Messages: 1,076

Congrats, spork !
Use a normal jail, pretty much where I started with this post, but add some commands to the vpn up/down script to run "jail -m new_vpn_ip,local_lan_ip", which should allow the jail to keep running, but adjust for any VPN IP changes. This seems easier...
If it were me. That's pretty close to the direction I would travel.

Careful tho. I think you may be trying to over complicate things a little.

--Chris
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

Well, I never played with VIMAGE before, and I figure it's going to either show up in 11.3 or 12.1 will be a safe release when it arrives.

So VIMAGE makes this really easy, as you have a little virtualized network stack in the jail. Just add an "unhide" rule for "tun*" in the jail's devfs ruleset and you can run OpenVPN inside the jail. So far, it's been working great. To protect from possible VPN outages/failures, I've simply limited access from this jail's IP at my pfsense box so that it can only reach the VPN server IPs. VPN goes down, jail is not going to "leak"...

Biggest pain with all of this is that the 3rd party tools that manage jails (iocage, iocage-new, cbsd) have really outpaced the handbook and other documentation - I found the easiest way to figure out VIMAGE (and the resoure limits that I'm not using, but was curious about) was to poke at the iocage source/scripts.
 

PMc

Daemon

Reaction score: 746
Messages: 1,494

Basically, I need to get "tun0" inside the jail AND allow for a dynamic IP on that interface.

Not necessarily. I am using the same configuration as You describe (host is connected to normal network, while jail talks via VPN to a special outside world and is reachable from there), only that my jail has a costant/static IP for that purpose.

My openvpn runs outside of the jail (started from jail.conf with exec.poststart), the tunX is configured with private IPs 10.1.1.26 <-> 10.1.1.20 (these are never routed), and the actually used static IP is an alias on lo0:
Code:
lo0       - 127.0.0.0/8   127.0.0.1            35722     -     - 10917909     -     -
lo0       - 198.51.100.23/32   198.51.100.23          50913     -     -    19210     -     -
tun1   1411 <Link#11>     tun1                 29656     0     0    45021     0     0
tun1      - 10.1.1.26/32 10.1.1.26               0     -     -    10067     -     -
Then the jail has ip4.addr = "198.51.100.23"; so that incoming traffic will get to the jail, and the outgoing routing is done with ipfw, like this:
ipfw add 15501 fwd 10.1.1.20 tcp from 198.51.100.23 smtp,ssh,ftp,http,https to not 192.168.0.0/16

The remaining difficulty is how to make such work for a dynamic IP, i.e. how to tell the jail to change it's IP.
 
OP
spork

spork

Active Member

Reaction score: 14
Messages: 163

The remaining difficulty is how to make such work for a dynamic IP, i.e. how to tell the jail to change it's IP.

Yeah, that's why I pretty much went with another option - I need to use the dynamic IP my provider supplies and I really hate enabling ipfw/ipf/pf on an internal host unless there's good reason to. VIMAGE has been working great. A billing issue with the vpn provider also confirmed to me that the "block all but vpn traffic" rules are working on my pfsense box in front of all this mess.
 
Top