Tag Archives: Networking

Unshallow Git

A while back, when I was working on some changes for FreeBSD, I wanted to checkout our source tree. A very typical thing that every developer does every day, that is

git clone https://git.FreeBSD.org/src.git

However, the FreeBSD git server is pretty far from me. There’s a GeoDNS system in the front so I usually hit the one in Frankfurt, Germany.

Still, it’s pretty slow!

root@devbsd14:~ # git clone https://git.FreeBSD.org/src.git
Cloning into 'src'...
remote: Enumerating objects: 4234853, done.
remote: Counting objects: 100% (381211/381211), done.
remote: Compressing objects: 100% (28321/28321), done.
Receiving objects:   3% (152416/4234853), 48.97 MiB | 1.08 MiB/s

Okay, 1.08 MiB/s is not that bad, but I’m sure we can do better.

How about GitHub?

root@devbsd14:~ # git clone https://github.com/freebsd/freebsd-src/
Cloning into 'freebsd-src'...
remote: Enumerating objects: 4793378, done.
remote: Counting objects: 100% (398/398), done.
remote: Compressing objects: 100% (233/233), done.
Receiving objects:  16% (780550/4793378), 223.95 MiB | 2.13 MiB/s

Okay, 2.13 MiB/s is also not bad, but I have a faster connection than that!

Regardless, I needed just the last state of the code, without the history, so in order to save time and bandwidth I can do

git clone --depth 1 https://git.FreeBSD.org/src.git

And now I can work.

The problem is that this was months ago, and I totally forgot about it.

While I was debugging some issue, I ran git blame and I realized that I can’t see anything older than 3 months. what?

Lucky me, I was able to understand what I did by looking into the shell history.

Okay, so two questions.

  1. Can I get the rest of the depth/history?
  2. If GitHub and git.FreeBSD.org is slow, can I setup a local mirror?

Turns out, I had to ask these questions in reverse.

First, I setup a FreeBSD source tree mirror in my home server (which also serves this blog). The connection to that server is fast, the download speed is around 500Mbps, compared to the 50Mbps that I get in this apartment. Yes, I have to apartments, but one of them is only for servers 😀

That was pretty easy to do, I just needed to tell Gitea to mirror https://git.FreeBSD.org/src.git, and in couple of minutes, it was all ready.

Next, I had to make my local checkout… unshallow. After setting up the appropriate remotes, all I had to do was

git pull --unshallow mirror main

and now I have the history all the way back to Jun 12, 1993.

Oh, right! The clone speed test!

root@devbsd14:~ # git clone git@git.bsd.am:antranigv/freebsd-src.git
Cloning into 'freebsd-src'...
remote: Enumerating objects: 4235021, done.
remote: Counting objects: 100% (4235021/4235021), done.
remote: Compressing objects: 100% (824757/824757), done.
Receiving objects:  18% (762304/4235021), 207.13 MiB | 3.53 MiB/s

Okay! now this does use a lot more speed!

Lessons Learned?

  1. Latency matters! If the distance between my two apartments is $2 worth of commute, while the FreeBSD server is $2000 worth of commute, then my apartments are also close to each other digitally.
  2. When you do anything non-standard with git (e.g. --depth=1) make sure to read the docs on how to undo that later.

That’s all folks…

Reply via email.

WireGuard “dynamic” routing on FreeBSD

I originally wrote about this on my Armenian blog when ISPs started blocking DNS queries during and after the war. I was forces to use either 9.9.9.9, 1.1.1.1, 8.8.8.8 or any other major DNS resolver. For me this was a pain because I was not able to dig +trace, and I dig +trace a lot.

After some digging (as mentioned in the Armenian blog) I was able to figure out that this affects only the home users. Luckily, I also run servers at my home and the ISPs were not blocking anything on those “server” ranges, so I setup WireGuard.

This post is not about setting up WireGuard, there are plenty of posts and articles on the internet about that.

Over time my network became larger. I also started having servers outside of my network. One of the fast (and probably wrong) ways of restricting access to my servers was allowing traffic only from my own network.

I have a server that acts as WireGuard VPN Peer and does NAT-ing. That being said, the easiest way for me to start accessing my restricted servers is by doing route add restricted_server_addr -interface wg0.

Turns out I needed to write some code for that, which I love to do!

Anytime that I need to setup a WireGuard VPN client I go back to my Armenian post and read there, so now I’ll be blogging how to do dynamic routing with WireGuard so I read whenever I need to. I hope it becomes handy for you too!

Now, let’s assume you need to add a.b.c.d in your routes, usually you’d do route add a.b.c.d -interface wg0, but this would not work, since in your WireGuard configuration you have a line that says

[Peer]
AllowedIPs = w.x.y.z/24

Which means, even if you add the route, the WireGuard application/kernel module will not route those packets.

To achieve “dynamic” routing we could do

[Peer]
AllowedIPs = 0.0.0.0/0

This, however will route ALL your traffic via WireGuard, which is also something you don’t want, you want to add routes at runtime.

What we could do, however, is to ask WireGuard to NOT add the routes automatically. Here’s how.

[Interface]
PrivateKey      = your_private_key
Address         = w.x.y.z/32
Table           = off
PostUp          = /usr/local/etc/wireguard/add_routes.sh %i
DNS             = w.z.y.1

[Peer]
PublicKey       = their_public_key
PresharedKey    = pre_shared_key
AllowedIPs      = 0.0.0.0/0
Endpoint        = your_server_addr:wg_port

The two key points here are Table = off which asks WireGuard to not add the routes automatically and PostUp = /usr/local/etc/wireguard/add_routes.sh %i which is a script that does add the routes, where %i is expanded to the WireGuard interface name; could be wg0, could be home0, depends in your configuration.

Now for add_routes.sh we write the following.

#!/bin/sh

interface=${1}

networks="""
w.x.y.0/24
restricted_server_addr/32
another_server/32
"""

for _n in ${networks};
do
  route -q -n add ${_n} -interface ${interface}
done

And we can finally do wg-quick up server0.conf

If you need to add another route while WireGuard is running, you can do

route add another_restricted_server -interface wg0

Okay, what if you need to route everything while WireGuard is running? Well, that’s easy too!

First, find your default gateway.

% route -n get default | grep gateway
    gateway: your_gateway

Next, add a route for your endpoint via your current default gateway.

route add you_server_addr your_gateway

Next, add TWO routes for WireGuard.

route add 0.0.0.0/1     -interface wg0
route add 128.0.0.0/1   -interface wg0

So it’s the two halves of the Internet 🙂

That’s all folks!

Reply via email.

VNET Jail HowTo Part 2: Networking

As always, Dan has been tweeting about VNET Jail issues, which means it’s time for another VNET Jail post.

This post assumes that you’ve read the original post on VNET Jail HowTo.

In Part two we will discuss Networking.

We will use PF as a firewall to do things like NAT.

If you need more help please check the FreeBSD Handbook: Chapter – Firewalls or send me an email/tweet.

At this point (from the last post) we were able to ping from the Jail to the Host.

root@www:/ # ping -c 1 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes
64 bytes from 10.0.0.1: icmp_seq=0 ttl=64 time=0.087 ms

--- 10.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.087/0.087/0.087/0.000 ms

Now we will setup PF on the host by adding the following to /etc/pf.conf

ext_if="em0"
jailnet="10.0.0.0/24"

nat pass on $ext_if inet from $jailnet to any -> ($ext_if)

set   skip on { lo0, bridge0 }
pass  inet proto icmp
pass  out all keep state

We also need to enable IP Forwarding in the kernel

Add the following in /etc/sysctl.conf

net.inet.ip.forwarding=1

And now execute

sysctl -f /etc/sysctl.conf
service pf restart

That should be it, now your Jail should be able to ping the outside world

root@zvartnots:~ # jexec -l www
You have mail.
root@www:~ # ping -c 1 9.9.9.9
PING 9.9.9.9 (9.9.9.9): 56 data bytes
64 bytes from 9.9.9.9: icmp_seq=0 ttl=61 time=2.566 ms

--- 9.9.9.9 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 2.566/2.566/2.566/0.000 ms
root@www:~ # 

If you setup a resolver, you should also be able to ping domain names as well.

root@www:~ # echo 'nameserver 9.9.9.9' > /etc/resolv.conf 
root@www:~ # ping -c 1 freebsd.org
PING freebsd.org (96.47.72.84): 56 data bytes
64 bytes from 96.47.72.84: icmp_seq=0 ttl=53 time=133.851 ms

--- freebsd.org ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 133.851/133.851/133.851/0.000 ms

Now, for a more complicated setup that assumes no firewalls and multiple IP addresses, where each Jail has its own IP address. I have a similar setup at home where my ZNC server Jail has its own IP address by connecting the physical NIC to the same bridge as the ZNC Jail.

In my rc.conf on the host

ifconfig_em0="inet 192.168.0.34 netmask 255.255.255.0"
defaultrouter="192.168.0.1"

cloned_interfaces="bridge0"
ifconfig_bridge0="addm em0"

Here’s an example with jail.conf

znc {
	$id		= "52";
	$addr		= "192.168.0.252";
	$mask		= "255.255.255.0";
	$gw		= "192.168.0.1";
	vnet;
	vnet.interface	= "epair${id}b";

	exec.prestart	= "ifconfig epair${id} create up";
	exec.prestart	+= "ifconfig epair${id}a up descr vnet-${name}";
	exec.prestart	+= "ifconfig bridge0 addm epair${id}a up";

	exec.start	= "/sbin/ifconfig lo0 127.0.0.1 up";
	exec.start	+= "/sbin/ifconfig epair${id}b ${addr} netmask ${mask} up";
	exec.start	+= "/sbin/route add default ${gw}";
	exec.start	+= "/bin/sh /etc/rc";

	exec.poststop   = "ifconfig bridge0 deletem epair${id}a";
	exec.poststop  += "ifconfig epair${id}a destroy";

	host.hostname = "${name}.bsd.am";
	path = "/usr/local/jails/${name}";
 	exec.consolelog = "/var/log/jail-${name}.log";
	persist;
}

And that’s pretty much it!

That’s all folks.

Reply via email.

FreeBSD USB Disk and ZVOL Encryption with GELI

Disk encryption is becoming more important in our day to day life, specially when you have access to some corporate servers or “top secret” files.

I love FreeBSD, it’s simple, rock-solid, easy to use, the handbook is amazing! It also has the option to encrypt the disks during installation. I use FreeBSD everywhere (and TrueOS on my laptop), but disk encryption takes a lot of power, so I chose instead of doing full disk encryption in my laptop, I’ll just have a small media like a USB drive or ZFS ZVOL and encrypt that.

Here’s how to do so 🙂

If you compiled your own kernel ensure it contains these options

options GEOM_ELI
device crypto

Now, make sure crypto and geom_eli is loaded and add these lines to /boot/loader.conf:

crypto_load=YES
geom_eli_load=YES

Let’s move on.

Now, we need the partition that we are going to encrypt it.
In case it’s a USB drive that you want to encrypt, here’s what to do. First, plug-in the USB drive into your computer. Now, let’s check it’s GEOM class name.

# geom disk list
Geom name: ada0
Providers:
1. Name: ada0
   Mediasize: 480103981056 (447G)
   Sectorsize: 512
   Mode: r1w1e2
   descr: SanDisk Ultra II 480GB
   lunid: 5001b444a4a40542
   ident: 162265428493
   rotationrate: 0
   fwsectors: 63
   fwheads: 16

Geom name: da0
Providers:
1. Name: da0
   Mediasize: 4004511744 (3.7G)
   Sectorsize: 512
   Mode: r0w0e0
   descr: SanDisk Cruzer Fit
   lunname: SanDisk Cruzer Fit      4C532000030211123165
   lunid: SanDisk Cruzer Fit      4C532000030211123165
   ident: 4C532000030211123165
   rotationrate: unknown
   fwsectors: 63
   fwheads: 255

Destroy and Create New Partitions

Okay, as we can see it’s da0. First, let’s destroy it and make a new partition on it! (Make sure you backup your data in case you have any important files).

# gpart destroy -F da0
da0 destroyed
# gpart create -s GPT da0
da0 created
# gpart add -t freebsd-ufs -i 1 da0
da0p1 added

In my case, I didn’t want to use a USB drive, I wanted to have an encrypted ZVOL, here’s how to do that as well.
First, create a ZVOL

# zfs create -V 1G zroot/private

Okay, so, in case of a USB drive, we have a partition waiting for us, in case of ZVOL, we have 1GB volume.

Let’s encrypt those!

Initiating Encryption

There are multiple ways to encrypt a disk, check geli(8) for detailed info. Here I’ll show you two options.

  • Encrypting with a master key that is protected with a passphrase.
  • Encrypting with a passphrase only.

For the first option first, generate a key!

# dd if=/dev/random of=/root/master.key bs=64 count=1

Now we initialize the provider which needs to be encrypted.

# geli init -s 4096 -K /root/master.key /dev/da0p1

or in case of ZVOL

# geli init -s 4096 -K /root/master.key /dev/zvol/zroot/private

You’ll be asked to enter your passphrase, twice.

For the second option, it’s exactly the same command without -K /root/master.key. So for the ZVOL it would be

# geli init -s 4096 /dev/zvol/zroot/private

Attaching Encrypted Disks

Now we can attach the provider with the generated key or without it, here’s an example.

# geli attach -k /root/master.key /dev/da0p1

You will be asked for your passphrase.
Or without the key, only the passphrase, here’s an example.

# geli attach /dev/zvol/zroot/private

This creates a new device with .eli extention:

# ls /dev/zvol/zroot/private
private.eli%    private%

Create New File System

First, let’s randomize whatever is on the device and then format it with UFS file system.

# dd if=/dev/random of=/dev/zvol/zroot/private.eli bs=1m
# newfs /dev/zvol/zroot/private.eli

Mount and Use

# mount /dev/zvol/zroot/private.eli /mnt/private
# echo 'some data' > /mnt/private/mytopsecretdata

Detaching Encrypted Volume

# umount /mnt/private
# geli detach /dev/zvol/zroot/private.eli

That’s all folks! 🙂

Reply via email.