Multilingual blog
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2023-05-14 12:19:04 +02:00
commit 9862b5aa22
19 changed files with 305 additions and 1 deletions

28
content/en/about.md Normal file
View file

@ -0,0 +1,28 @@
---
title: "Pierre-Olivier `nemunaire`"
date: !!timestamp '2017-07-31T00:50:07+02:00'
update: !!timestamp '2021-07-24T00:00:00+01:00'
---
{{<icon "fa fa-briefcase about-icon">}}
Currently **entrepreneur** in various businesses. Previously worked as **devops** for [Novaquark](http://novaquark.com), prior to worked as **embedded software engineer** at [Qarnot computing](https://qarnot.com/), then **Chief Information Security Officer** and **senior software architect** at [Qarnot computing](https://qarnot.com/).
{{<icon "fa fa-graduation-cap about-icon">}}
After 5 years in [Epita](http://epita.fr/), in 2014, I am a graduate engineer! I was following the [***System, Network and Security***](https://srs.epita.fr/) classes.
{{<br>}}
During my studies, I was *root* of the [*assistants'*](https://assistants.epita.fr/) laboratory and of the *System, Network and Security* laboratory.
{{<icon "fa fa-terminal about-icon">}}
With my rich creativity, I'm always working on a lot of amazing projects.
I spend most of my free time to improve system support, document and **promote ARM-based computer**, whether server or desktop.
{{<br>}}
Check out my [gitea instance](https://git.nemunai.re) or my [GitHub account](https://github.com/nemunaire).
{{<icon "far fa-thumbs-down about-icon">}}
You won't find me on any social network, because I don't have time to sell my privacy for free (and I fight against most of them).
{{<icon "fa fa-heart about-icon">}}
I'm crazy about any knowledge (mainly focus on sciences, typography, society, companies, faune and flora, ...) and am looking for more freedom and independence.
{{<icon "fa fa-drum about-icon">}}
On my spare time, I also [play drums](https://storage.nemunai.re/scores/_list.html) and [cook](https://food.p0m.fr/).

6
content/en/books.md Normal file
View file

@ -0,0 +1,6 @@
---
title: "Books"
date: !!timestamp '2022-03-02T15:10:10+01:00'
---
I publish my first book in March 2022. It is written in french.

View file

@ -0,0 +1,41 @@
---
title: Linux Kernel Configurations
date: !!timestamp '2015-04-20 00:00:00'
update: !!timestamp '2019-08-13 14:15:00'
tags:
- kernel
---
My favorite distribution is [Gentoo], for 7 years now.
It allows me to have all the flexibility I need (the perfect world between stability with only legacy packages or recent ones on a constantly broken system; as in Gentoo, you always have choice) and it teaches me so many things each day.
As I'm used to control everything, here is a list of kernels' configurations I use currently.
<!--more-->
* [Dreamplug]: latest public Grsecurity kernel 4.9 (before, I used precompiled kernels from [Xilka]);
* [Cubieboard 2]: latest mainline kernel, currently 5.2;
* [Odroid-C1]: Linux 3.10 [custom branch](https://github.com/hardkernel/linux.git) for the Amlogic S805 (quad-core ARMv7 Cortex-A5 and Mali450) + upstream patches on 3.10 not merged in the Hardkernel tree;
* [Mirabox]: latest public Grsecurity kernel 4.9;
* [Cubox-i 4x4]: latest mainline kernel, currently 4.16, running OpenGL applications through etnaviv driver;
* [Creator CI20]: Linux 3.18 [custom branch](https://github.com/MIPS/CI20_linux.git) for the Ingenic JZ4780 SoC + [upstream patches](https://github.com/nemunaire/CI20_linux.git) on 3.18 not merged in the imgtec tree;
* [ThinkPad X250]: latest mainline kernel, currently 5.1.
* [Orange Pi PC]: latest mainline kernel, currently 5.2 on headless server.
* [VoltaStream AMP1] & [VoltaStream Zero]: Linux 4.9 [custom branch](https://github.com/polyvection/linux-imx.git) for [i.MX6ULL](http://git.freescale.com/git/cgit.cgi/imx/linux-imx.git) + [upstream patches](https://github.com/nemunaire/linux-imx.git) on 4.9 not merged in the PolyVection tree.
* [Pine A64]: latest mainline kernel, currently 5.0 on headless server.
* [Helios4]: latest mainline kernel, currently 5.2 on headless server.
[Gentoo]: http://www.gentoo.org/
[Dreamplug]: http://www.globalscaletechnologies.com/p-54-dreamplug-devkit.aspx
[Xilka]: http://www.xilka.com/sheeva/
[Odroid-C1]: http://www.hardkernel.com/main/products/prdt_info.php?g_code=G141578608433
[Cubieboard 2]: http://cubieboard.org/model/cb2/
[Mirabox]: http://www.globalscaletechnologies/p-58-mirabox-java-devkit.aspx
[Cubox-i 4x4]: http://www.solid-run.com/product/cubox-i-4x4
[Creator CI20]: http://store.imgtec.com/uk/product/mips-creator-ci20/
[ThinkPad X250]: https://wiki.gentoo.org/wiki/Lenovo_Thinkpad_X250
[Orange Pi PC]: http://www.orangepi.org/orangepipc/
[VoltaStream AMP1]: https://web.archive.org/web/20190323152013/https://voltastream.com/product/voltastream-amp1/
[VoltaStream Zero]: https://web.archive.org/web/20190323152013/https://voltastream.com/product/voltastream-zero/
[Pine A64]: https://www.pine64.org/devices/single-board-computers/pine-a64/
[Helios4]: https://kobol.io/

View file

@ -0,0 +1,108 @@
---
title: Multi-Hosts TLS Certificate
date: !!timestamp '2022-02-09 00:00:00'
tags:
- certificates
- web
---
It is sometimes convenient to have a domain distributed over two or more machines.
This technique, as old as DNS, is interesting to spread the load between multiple hosts, or to provide a bit of high availability.
Indeed, if a host becomes inaccessible, at least half of the requests will continue to be successful.
However, since TLS connections have become the norm, and certificates should be renewed automatically, it could be hard to control the validation and the distribution.
I will present you a technique which, with the help of a finely configured web server, allows to get a different certificate on each machine, but usable for the same subdomain.
<!--more-->
The trick is, when receiving the verification request, to either serve the file if you have it, or to transmit the request to the next server: it will return the file if it has it, or will return a 404 error.
You have to be careful not to create loops, because you can quickly end up in a situation where no machine has the requested file and therefore calls the next one which does not have it either...
## Use case
This trick is helpfull in a small setup: with more than 3 or 4 servers, it is better to use a deployment strategy between hosts, for example based on ACME client hooks: after validation, the client initiates a connection to the other servers to update their certificate and notify their respective web servers.
I made this installation for my minio servers: each one is accessible through `minio.nemunai.re` but also individually on `minio0.nemunai.re` and `minio1.nemunai.re`. The two servers are in a distinct geographic area, and are not able to execute commands on each other.
So I tried to create two independent certificates, one for each machine:
- the first host must obtain a certificate for `minio0.nemunai.re` and `minio.nemunai.re` ;
- the second host must obtain a certificate for `minio1.nemunai.re` and `minio.nemunai.re`.
At the end, each of the two servers will be able to answer the requests of `minio.nemunai.re`, our goal, whatever the status of the other machine.
Let's Encrypt doesn't revoke certificates already issued for a domain, so both certificates are valid at the same time for the same domain.
## DNS Configuration
Since we want to keep the architecture simple, we are leaving the load balancing to the DNS: good resolver implementations will do round-robin over our records, ensuring a distribution of clients between each host.
The first step is to create our sub-domains as follows:
```
minio0.nemunai.re. 3600 IN A 198.51.100.10
minio1.nemunai.re. 3600 IN A 198.51.100.11
```
This registers a dedicated domain for each host (so we can access it easily when needed).
Then we register the common domain with which we will do load-balancing:
```
minio.nemunai.re. 3600 IN A 198.51.100.10
3600 IN A 198.51.100.11
```
We do the same for `AAAA` records, with IPv6 address.
## Reverse Proxy Configuration
We know that when using the ACME http-01 test, we'll receive a request on `minio.nemunai.re/.well-known/acme-challenge`.
But the problem we have to solve is that when one of the servers will ask for a certificate, the validation request has a 50% chance to arrive on the other host.
This is where we will configure the reverse proxy in order to send the request to the next server if it does not have the answer of the challenge.
On both servers, we'll handle `acme-challenge` that way:
```
location /.well-known/acme-challenge {
alias /var/lib/acme/webroot;
try_files $uri $uri/ @minio_neighbor;
}
```
And we also need that the default server handle `acme-challenge`s in the same directory:
```
server {
listen 80 default;
[...]
location /.well-known/acme-challenge {
alias /var/lib/acme/webroot;
}
}
```
With the [`try_files`](http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files) instruction, our reverse proxy will first look for the file in the local directory, then, if it doesn't exists, it forwards the request to its neighbor server `@minio_neighbor`.
We declare `@minio_neighbor` in another block:
```
location @storage_neighbor {
proxy_pass http://198.51.100.11;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
```
On the other server, we'll obviously use the address of the other host.
This configuration avoid infinite proxy loop, as if the challenge response is not find localy, we ask the other host, but it'll not pass through the `try_files` file as this is the default server that'll respond. If it's the other host that have the challenge response, the first server asked will answer it thanks to the proxy, otherwise, the proxify answer will be a 404 error.
And that's it: we can launch our ACME client on both host, each one can handle the challenge reponse of the other.

View file

@ -0,0 +1,58 @@
---
title: PGP key
date: !!timestamp '2015-06-29 00:00:00'
update: !!timestamp '2021-07-24 00:45:00'
tags:
- privacy
- cryptography
---
My personal PGP key is the following: [0x842807a84573cc96].
pub 4096R/4573CC96 2014-06-23 [expires: 2022-06-30]
Key fingerprint = E722 B5B7 3CA7 FA93 5FC1 AA09 8428 07A8 4573 CC96
uid Pierre-Olivier Mercier <nemunaire@nemunai.re>
sub 4096R/9D2855C3 2014-06-23 [expires: 2022-06-30]
<!--more-->
I use PGP on a daily basis: each e-mail I sent is at least signed. Don't hesitate to send me encrypted or signed message.
My keyring is stored on a tamper resistant USB token (a [Nitrokey Pro]).
This is the only method I use to sign, encrypt and sometimes to [authenticate](#ssh-authentication).
## DANE
My key is also available through [OpenPGP DANE].
You can retrieve it using `gpg` via:
```sh
gpg2 --auto-key-locate clear,dane -v --locate-key nemunaire@nemunai.re
```
I used [this script](https://gist.github.com/nemunaire/447c989e9f098c679edb) to generate the record.
With modern version of `gnupg`, it is also possible to get the DNS entry with the following command:
```sh
gpg2 --export-options export-minimal,export-dane --export 0xKEYID
```
## SSH Authentication
Sometimes I use my dedicated PGP key to log me on a remote SSH server. Here is its corresponding public ssh key :
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCnABr9AhXL9AYBQnM0GRcR9yLaKheLcxXykTSEbKP4X/R5BElSS5iF+T+MPi1ym7AtcuFcHXqNdEhb3j6zvqk3sY069sg0zio/jQzWTtKjYVtCiE4SleFrb5I012IwFhPCUArVqhHrfuj8wtg5isl1CSIYii+bpFLbrAGqBcydfcN/Z/vd7jbGEdmHR1RYwE+TzJl1aPiWpqMg9PyaJudNcuxrWjHcHtAomT0CGn2OGREUZS9rcFomCqw7JW9moaWqDSaW+aNX+xTJISo6TiAB4nNOpvTMl6BWPJ5e2eqn4xQACuTb/EVCuAJGeQ8BQudanxRXrfpdgHATsJxldTau2CCmIrZrg2We0ZfiGZ7KEwf3isAyzH9FK/gmb29XeDfvE/UpTTijaPo8xgiH3Ag0ZBk1wb3PVneN9fQGpVogOxR/HwfqOl376N6kTQIhvAFaU/wJnHQ4Z0CBekOxC9XptrihUdW7ashP6arrhYzlyNUPrRGiLmab9jsqsvP7aDRFEpWa/cd9nD2Mp1JNj51ZeqwT5Juo3ElMCfoTy5IAyc6QUTtIdYRgukLjiO8k5NBi8/Yzm1lNzf3cRZdh5ZIS0AUO2Celi97WXiHrU841OqsuMBgdCDnOuG3X8qU+pyT7836XSjglLEwABtXUSWULf06AoPVJe4+cxi3NWfxJiQ==
## Teaching PGP
Each year, I ask my students at [EPITA](https://www.epita.fr/), a French computer science school, to sign their work when they send them to me, by e-mail.
As it is not always easy for them, I developed a script to automatically check the correctness of their signature: [peret](https://git.nemunai.re/srs/peret).
[0x842807a84573cc96]: http://pgp.mit.edu/pks/lookup?op=vindex&search=0x842807A84573CC96
[Nitrokey Pro]: https://shop.nitrokey.com/shop/product/nitrokey-pro-3
[OpenPGP DANE]: https://tools.ietf.org/html/rfc7929

View file

@ -0,0 +1,27 @@
---
title: RTL8153B support for 4.9 kernel
date: !!timestamp '2019-03-17 00:00:00'
tags:
- kernel
---
If you buy a *recent* USB to Ethernet adapter, embedding a Realtek chip, you
possibly face, like me, the following error, when connecting it:
```
r8152 4-1.1:1.0 (unnamed net_device) (uninitialized): Unknown version 0x6010
r8152 4-1.1:1.0 (unnamed net_device) (uninitialized): Unknown Device
```
<!--more-->
This error is raised because your Linux r8152 driver is too old and doesn't
support your chip's variant.
In my case, I got the variant `0x6010` which has only been implemented in Linux
4.13, in the [commit
65b82d69...d3e7fb976](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/net/usb/r8152.c?h=v4.13&id=65b82d696b9e84fda6dd7df61801b57d3e7fb976).
As I run at the time a 4.9 kernel and can't upgrade to a newer release, I
backport the commit to the 4.9 branch. You can find [the patch I made
here](r8152-for-4.9.patch). It only adds support for RTL8153B.

View file

@ -0,0 +1,124 @@
---
title: Slow memhog for testing cgroups
date: !!timestamp '2016-10-04 00:00:00'
tags:
- teaching
---
Testing the cgroup memory is not something as easy as we can think. It can't be
only question of `malloc(100000)` in a loop, as the Linux kernel overcommit
memory allocation: so even if we get effectively a 100000 bytes long memory
space, this doesn't decrease the physical available memory. To do so, this
space need to be changed pages by pages, that can be tedious to do. And quite
uncertain, because the kernel can take advantage of the swap partition...
To facilitate memory testing, there is `memhog`, part of `numactl` tools. It
aims to allocate large memory block for testing, directly in the physical
memory.
<!-- more -->
If we ask memhog to allocate 100M, 1G, 5G, 10G, ... it'll actually ask the
kernel for such amont of memory, in no time. If there is enough memory
available, we got our 100M, 1G, 5G, ... and the available memory is really
decreased by such volume.
In my demos, I need a slightly different behaviour, to demonstrate what happens
as a function of time.
I slightly modify `memhog` to introduce a timer between slice allocation.
```c
/* Derivative work of memhog.c from the numactl repository,
hosted at https://github.com/numactl/numactl.git
Copyright (C) 2016 Pierre-Olivier Mercier, EPITA.
Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
numactl is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; version
2.
numactl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should find a copy of v2 of the GNU General Public License somewhere
on your Linux system; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
char *
alloc_workbuf(size_t size)
{
char *ptr;
/* allocate some memory */
ptr = malloc(size);
/* return NULL on failure */
if (ptr == NULL)
{
fprintf(stderr, "Unable to malloc %zuk: %s\n", size / 1024, strerror(errno));
return NULL;
}
/* lock this buffer into RAM */
if (mlock(ptr, size)) {
free(ptr);
if (errno == ENOMEM)
fprintf(stderr, "Unable to lock memory: not enough permissions\n");
else
perror("Unable to lock memory");
return NULL;
}
return ptr;
}
int
main(int argc, char *argv[])
{
size_t size;
size_t steps = 32;
/* parse arguments */
if (argc < 2 || argc > 3) {
fprintf(stderr, "Usage: memhog <size in MB> [nb steps]\n");
return EXIT_FAILURE;
}
size = atoi(argv[1]);
if (argc > 2)
steps = atoi(argv[2]);
size = size / steps;
/* Do stuff */
for (size_t i = 0; i < steps; i++)
{
if (!alloc_workbuf(size * 1000000UL))
break;
printf(".");
fflush(stdout);
usleep(80000);
}
printf("\n");
return EXIT_SUCCESS;
}
```
You can compile those C lines with just `make`, stating your file is named `memhog.c`:
```shell
make memhog
```

View file

@ -0,0 +1,75 @@
---
title: My private SSH keys managment
date: !!timestamp '2015-02-19 00:00:00'
update: !!timestamp '2017-07-23 22:45:00'
tags:
- cryptography
- ssh
---
I always have a different SSH key pair per machine. The aim is to really never copy my private key from a machine to another over network or USB stick.
<!--more-->
## Client keys
With this approach, if one of my host is compromised and/or my key could have been exposed, I have only to remove granted access to this key to host or services (OK, that can be painful to find such services), but I can continue to use other no-compromised keys to work.
As you can see on my [github](https://github.com/nemunaire.keys) account, I've registered several keys, because I don't work from the same machine every time.
It can sometime be complicated to give me access to machine, but in most case, I tend to centralize most of my outgoing connections from a single host, which is in fact my home desktop: oupaout.
Here is a list of my keys' md5 fingerprints:
* `assouan`
* [`aton`](aton_ed25519.pub): 0d:89:02:4a:45:51:0c:43:e8:be:2e:99:38:5b:88:0e (ED25519)
* [`aton`](aton_rsa.pub): ee:61:d5:bf:b0:23:93:1a:bb:32:ef:34:10:fb:aa:77 (RSA 4096)
* `bastet` (legacy): 4a:51:80:24:b0:69:7a:59:fc:44:08:29:aa:15:42:5b (RSA 4096)
* EPITA personal rack (legacy): 91:95:bc:4e:e7:b2:5b:9c:7f:71:4a:7d:0a:43:80:17 (RSA 4096)
* EPITA SSH gate (legacy)
* EPITA YACKU laboratory (legacy): 80:7c:8e:42:53:ee:0f:b5:27:d5:63:ab:b4:5a:46 (RSA 4096)
* [`khonsou`](khonsou_ed25519.pub): 0d:89:02:4a:45:51:0c:43:e8:be:2e:99:38:5b:88:0e (ED25519)
* khonsou_old: f5:dc:fd:db:c8:ce:ec:df:33:86:54:58:05:7e:d2:74 (ED25519)
* `montou`: this machine can't be used as outgoing host.
* `nout`: this machine can't be used as outgoing host.
* `nout_old`: e8:69:71:3c:5e:cc:3c:d5:7d:a2:67:30:a9:35:df:24 (RSA 4096)
* [`ouaset`](ouaset.pub): 5e:01:65:8c:ae:9e:6e:f3:a5:88:80:16:fa:bf:d6:ac (ED25519)
* [`oupaout`](oupaout.pub): 30:04:ad:11:57:e0:e9:dc:a2:e0:d2:65:cd:60:9a:ab (ED25519)
* [Rescue key](rescue.pub): 30:15:a7:3f:0b:51:7a:53:7b:47:bd:00:21:55:ee:bd (RSA 4096)
* `satis`: this machine has no key pair yet.
* [`seth`](seth_ed25519.pub): 6a:1f:05:60:fa:6b:32:f3:2d:ba:e3:36:e7:6b:7b:13 (ED25519)
* [`seth`](seth_rsa.pub): 03:a9:3a:3a:e1:e0:99:24:69:15:cb:a5:58:5c:3f:6c (RSA 4096)
* `seth_old`: 97:8c:bc:9a:ec:62:8d:b8:1a:88:b1:0d:d9:62:1a:04 (RSA 4096)
### Get the fingerprint from a private or public key file
```sh
ssh-keygen -l -E md5 -f KEY_FILE
```
### Usign PGP
Sometime, I use my authentication PGP key as SSH key. Read the [related article]({{< relref "/post/pgp_key.md#ssh-authentication" >}}) to view the public key.
## Server keys
The `nemunai.re` domain, contains [SSHFP] records for each physical host. To avoid answering this message without further checks:
The authenticity of host 'nemunai.re (203.0.113.42)' can't be established.
RSA key fingerprint is 00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff.
Are you sure you want to continue connecting (yes/no)?
you can use the following command: `ssh -o "VerifyHostKeyDNS yes" $HOSTNAME.nemunai.re`
[SSHFP]: http://tools.ietf.org/html/rfc4255
### Generate SSHFP records
SSHFP records can be generated with the following command:
```sh
ssh-keygen -r HOSTNAME
```

View file

@ -0,0 +1,70 @@
---
title: Use the additional IPv6 blocks of the Free and Orange network
date: !!timestamp '2023-04-05 14:43:00'
tags:
- network
- ipv6
- freebox
---
With Free and Orange, when IPv6 is not disabled, the Freebox (and some Livebox) provide a /64 IPv6 range to the connected equipment.
But it turns out that it is a /60 range that is available and usable by each subscriber.
This represents a total of 8 addressable /64 networks.
Let's see what it can be used for and how to use it.
<!-- more -->
# IPv6 reminders
Contrary to IPv4, with IPv6 one avoids making NAT, i.e. one allocates to each machine on the network an IPv6 address directly routable on Internet.
Of course it is always necessary to go through the router (the box) which is then used as a simple gateway to the Internet.
In IPv6, devices are able to choose their own IP, without the help of the DHCP protocol.
This is possible because the router regularly transmits information about the subnet in which you are located (this is the [Router Advertisement (RA)](https://en.wikipedia.org/wiki/Router_advertisement)).
For our experiment, let's take the following lab:
![The basic infrastructure that we will use for our experiments](lab.png)
We have all our equipment connected to the box and a series of virtual machines hosted on one of the network machines.
At this stage, if we want our virtual machines to be reachable from the Internet in IPv6, we have to configure the hypervisor network in *bridge* mode.\
Indeed if the network of our virtual machines is distinct from the network of the box, this one will not be able to communicate with our virtual machines. By using the *bridge* mode, we simulate the fact that the virtual machine is diconnected to the box, or to a switch. In any case no equipment requiring to make routing.
If our virtual machines are only IPv6 clients and are not intended to serve content directly on the Internet, this solution is perfectly acceptable. But if we want to serve content, we might want to segment our network to try to isolate the content. But if we want to serve content, we might want to segment our network to try to isolate the devices.
# Segment the network of the box
Because of the very large number of public IPv6 addresses that our operators provide us with, we could start by segmenting our network between our virtual servers and our other equipment: each would be in a separate subnet.
The main interest of this segmentation would be to avoid that all this little world shares the same subnet: as they can all communicate directly with each other, it is more complicated to filter efficiently malicious exchanges. For example, if one of the virtual machines exposed on the Internet is compromised, it can access all our local equipment (telephones, connected objects, etc.) which are not necessarily secure, or conversely, an object on the network can start to intercept all the data. network object can start intercepting all the traffic of the virtual machines by pretending to be the box.
We could therefore want to segment our network like this:
![Example of segmentation by splitting the /64 block into two /65 blocks](lab-segmente.png)
We would reserve half of the /64 block for real network equipment and allocate the other half to our virtual machines located on a server/Raspberry Pi.
Despite the large number of IPv6 addresses that can be assigned, it is not easy to subdivide our /64 to assign it to a secondary router or a virtual machine server. This segmentation is indeed not possible without changing the configuration of the box because it expects to be able to reach our virtual machines directly, without going through an intermediate machine/host/router.
However, we have access to the routing parameters of the other 7 /64 blocks distributed by the operator. We can for example assign one of them to the host of our virtual machines.
# Delegate an additional IPv6 prefix
As mentioned in the introduction, some operators make available to their subscribers a range of IPv6 addresses much larger than the /64 block of the main network.
Some ISP routers also make it possible to take advantage of additional blocks by offering to delegate the other blocks to machines on the network.
In concrete terms, this means that when the box receives a packet destined for one of the delegated blocks, it will not process it itself, but will transmit it to the machine designated as the recipient. In other words, it will route the traffic of this block to the designated router. And it doesn't have to be complicated!
# Different use cases
Now that we have seen the theory, let's look at different use cases, so we are not limited to our virtual machines:
- Use a /64 block to give IPv6 to its virtual machines
- [Use a /64 block to give IPv6 to your Docker containers]({{< relref "use-ipv6-in-docker.md" >}})
- Use a /64 block to have IPv6 in several isolated subnets
- Use a /64 block to have public IPv6 in your Wireguard tunnel

View file

@ -0,0 +1,44 @@
---
title: Use Gitolite Access Control In Gitweb
date: !!timestamp '2015-09-24 00:00:00'
update: !!timestamp '2019-04-09 12:45:00'
tags:
- git
---
Are you using gitolite and gitweb? Two nice and lightweight projects, but perhaps you are tired to manage access control in gitweb?
Here is some simple tricks to use gitolite access list directly into gitweb, automatically.
<!--more-->
As you may know, the configuration file
[`/etc/gitweb.conf`](https://git.kernel.org/pub/scm/git/git.git/tree/Documentation/gitweb.conf.txt#n15)
is in fact no less than a perl script fragment. As it is simply imported by
gitweb, it is possible to include some code.
[Gitolite](https://gitolite.com/) is also a piece of software writen in
Perl. So it is pretty easy to make gitweb relying on gitolite permissions. Here
is what I append to my `/etc/gitweb.conf`:
```perl
# Most of the code comes from https://gitolite.com/gitolite/gitweb.conf.html
# where comments live.
BEGIN {
$ENV{HOME} = "/var/lib/gitolite"; # Home of the gitolite user in gentoo
$ENV{GL_BINDIR} = "/usr/libexec/gitolite";
}
use Gitolite::Easy;
$ENV{GL_USER} = $cgi->remote_user || "gitweb";
$export_auth_hook = sub {
my $repo = shift;
return unless $repo =~ s/^\Q$projectroot\E\/?(.+)\.git$/$1/;
return Gitolite::Easy::can_read($repo);
};
```

View file

@ -0,0 +1,138 @@
---
title: Give IPv6 connectivity to its Docker containers using an IPv6 block from its ISP
date: !!timestamp '2023-05-04 15:10:00'
tags:
- network
- ipv6
- docker
---
It may seem surprising that a modern service like Docker does not offer IPv6 in containers by default, especially when in a network with IPv6.
In fact, for the same reason we saw in [the introductory article]({{< relref "use-additional-ipv6-blocks-from-isp.md" >}}), since the containers are in a virtual network, they cannot be reached by the box/router distributing the IPv6 subnet.
<!-- more -->
The same phenomenon can be observed with IPv4: each container has an IPv4 in a subnet separate from the one in which our host machine is located.
![Illustration of a classic IPv4 home network](common-network-with-docker.png)
In order for the containers to have access to the Internet under these conditions, in IPv4 NAT is implemented:
```
42sh$ iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 3 packets, 228 bytes)
pkts bytes target prot opt in out source destination
14713 978K MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
```
Since NAT is generally not done on IPv6, nothing similar is done by Docker in this sense.
# Docker as IPv6 router
Without IPv6 in a container, it is impossible for containers to address other services listening exclusively in IPv6 on the Internet.
In order for containerized programs to be able to connect to other services in IPv6, the *Enable IPv6* option must be activated and the prefix to be used must be defined through the *IPv6 Prefix* option.
Be careful, it is not enough to define these options, it is also necessary that the box correctly routes the packets to the destinations of the containers to your machine.
This is why we need to take advantage of the other IPv6 blocks provided by our operator. By telling the box the address of the machine hosting our containers, it will route all packets to the containers without question.
So not everything can be done exclusively on the machine, the network must also be configured. Let's start with that.
# Set up IPv6 prefix delegation on the Freebox
The router will ask us for the address (IPv6) to which it should route the packets. We usually indicate a [local link IP](https://en.wikipedia.org/wiki/Link-local_address).
So we start by looking at our local IPv6 on the outgoing link to the router.
⚠️ Be careful, all interfaces have a local address, they all start with `fe80:`, they are only valid on the network card considered. If you get the wrong address, nothing will happen (it won't break your network though).
In my case, it is the `eth0` interface that is connected to the router:
```
42sh$ ip address show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether fd:54:01:98:cd:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.0.42/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0
valid_lft 35141sec preferred_lft 35141sec
inet6 2a01:...:2420:24ac:f101:c280:50c2/64 scope global noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::5a43:3580:173c:395e/64 scope link noprefixroute
valid_lft forever preferred_lft forever
```
My local IP is therefore `fe80::5a43:3580:173c:395e`.
It is this IP that I will indicate in the configuration of the router.
On the Freebox, the window for setting additional prefixes is in "Paramètres de la Freebox", "Configuration IPv6", under the "Général" tab. It is the "Délégation de préfixe" box that will interest us.
It looks like this:
![Freebox IPv6 prefix delegation settings window](freebox-ipv6-prefix-delegation.png)
Always leave the first field empty, otherwise the box will not offer you IPv6 on the main network.
Indicate in the next empty field (normally the second one!) the local address retrieved earlier.
That's all! The hardest part is over. Now let's see the Docker configuration.
# Setting up Docker for IPv6
We will not use the range to which our machine is connected. We are going to use a whole /64 range, the one for which we have given the local IP of our machine to the box.
![Our prefix delegation correctly set up on the Freebox](freebox-ipv6-delegation-filled.png)
According to the previous screenshot, our configuration file `/etc/docker/daemon.json` should look like:
```
{
"ipv6": true,
"fixed-cidr-v6": "2a01:1234:abcd:2421::/64"
}
```
We restart Docker and we can test:
```
42sh$ docker run -it alpine
/ # ip address show eth0
58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:09 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.9/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 2a01:1234:abcd:2421:0:242:ac11:9/64 scope global flags 02
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:9/64 scope link
valid_lft forever preferred_lft forever
```
If you have an IPv6 in addition to the usual IPv4, Docker is correctly configured. To find out if the configuration on the box side was successful, let's do a `ping` in the container:
```
/ # ping ping6.online.net
PING ping6.online.net (2001:bc8:1::40): 56 data bytes
64 bytes from 2001:bc8:1::40: seq=0 ttl=52 time=11.008 ms
64 bytes from 2001:bc8:1::40: seq=1 ttl=52 time=8.822 ms
^C
--- ping6.online.net ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 8.822/9.915/11.008 ms
```
If the ping responds, it's all good: your containers will now have access to and be accessible in IPv6.
# Others use cases
This post is part of a series of posts on the use of additional IPv6 ranges:
- [Introduction: Use the additional IPv6 blocks of the Free and Orange network]({{< relref "use-additional-ipv6-blocks-from-isp.md" >}})
- Use a /64 block to give IPv6 to its virtual machines
- Use a /64 block to give IPv6 to your Docker containers
- Use a /64 block to have IPv6 in several isolated subnets
- Use a /64 block to have public IPv6 in your Wireguard tunnel

View file

@ -0,0 +1,29 @@
---
title: Support for the user namespace in grsecurity kernel
date: !!timestamp '2018-10-31 00:00:00'
tags:
- kernel
---
Grsecurity has completely disabled, [on
purpose](https://forums.grsecurity.net/viewtopic.php?f=3&t=3929#p13904), the
user namespace code for the kernel.
As the goal of this namespace is to gain (virtualy) root privilegies inside a
namespace (in theory, it shouldn't give more priviledgies than the one you
initialy have outside of your namespace), there are some interesting use cases,
or, in my case I need to perform some demo in front of my students.
<!--more-->
Other distros, like Debian, choose to allow the use of user namespace through a
custom kernel config variable. In order to use them without both
`CAP_SYS_ADMIN`, `CAP_SETUID` and `CAP_SETGID`, you need to activate (as root):
```bash
42sh# sysctl -w kernel.unprivileged_userns_clone=1
```
To reproduce the same behaviour with a grsecurity kernel, I made a patch, to
apply after the grsecurity patch:
[grsec-enable-user-ns.patch](grsec-enable-user-ns.patch).

38
content/en/talks.md Normal file
View file

@ -0,0 +1,38 @@
---
title: "Talks"
date: !!timestamp '2017-07-31T00:07:37+02:00'
---
Here are slides I used as support to my presentations:
* [[FR] Strong authentication](2fa.pdf)
* [[FR] Self-Hosting](autohebergement.pdf)
* [[FR] DNS overview](QTechNote%20DNS.pdf)
* [[FR] Docker hands-on](QTechNote%20Docker.pdf)
* [[FR] gRPC/Protobuf overview](QTechNote%20%231.pdf)
## Teaching
In [Epita](http://www.epita.fr/), I'm responsible for teaching containers usage and plumbing in a 15 hours course called [*light virtualization*](https://virli.nemunai.re/) and for [*ADvanced LINux administration*](https://adlin.nemunai.re).
Moreover, I coach students to create [an annual CTF](https://fic.srs.epita.fr/), at [FIC].
And also lead the related CTF [server developments](https://git.nemunai.re/fic/server).
[FIC]: https://www.forum-fic.com/
## Ideas
Following, some talks I started to work on:
* SSL client good practices (from Internet browser view)
* Unix daemons in systemd epoch
* HTTP/2
* Feedbacks on 5 years of self-hosting
* Feedbacks on 1 year without Intel CPU
* Linux PAM, how to
* Demystied Gentoo
* Git advanced usages by example
* Packets filtering via nftables
* The e-mail tech, today