Skip to content

Commit 7b6a2ed

Browse files
committed
Prepare to fully migrate
1 parent ac16e41 commit 7b6a2ed

15 files changed

+655
-11
lines changed

_config.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ theme: jekyll-theme-chirpy
99
lang: en
1010

1111
# Change to your timezone › https://kevinnovak.github.io/Time-Zone-Picker
12-
timezone:
12+
timezone: Europe/Bucharest
1313

1414
# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md
1515
# ↓ --------------------------
1616

17-
title: Merox # the main title
17+
title: merox.dev # the main title
1818

1919
tagline: Insights from my tech journey—homelab to real-world IT. # it will display as the subtitle
2020

@@ -59,7 +59,7 @@ webmaster_verifications:
5959
# Web Analytics Settings
6060
analytics:
6161
google:
62-
id: # fill in your Google Analytics ID
62+
id: RXSCNFY5WZ
6363
goatcounter:
6464
id: # fill in your GoatCounter ID
6565
umami:
@@ -109,10 +109,10 @@ toc: true
109109

110110
comments:
111111
# Global switch for the post-comment system. Keeping it empty means disabled.
112-
provider: # [disqus | utterances | giscus]
112+
provider: disqus # [disqus | utterances | giscus]
113113
# The provider options are as follows:
114114
disqus:
115-
shortname: # fill with the Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname
115+
shortname: merox
116116
# utterances settings › https://utteranc.es/
117117
utterances:
118118
repo: # <gh-username>/<repo>
@@ -181,7 +181,7 @@ defaults:
181181
toc: true # Display TOC column in posts.
182182
# DO NOT modify the following parameter unless you are confident enough
183183
# to update the code of all other post links in this project.
184-
permalink: /posts/:title/
184+
permalink: /blog/:title/
185185
- scope:
186186
path: _drafts
187187
values:

_data/locales/en.yml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# The layout text of site
2+
3+
# ----- Commons label -----
4+
5+
layout:
6+
post: Post
7+
category: Category
8+
tag: Tag
9+
10+
# The tabs of sidebar
11+
tabs:
12+
# format: <filename_without_extension>: <value>
13+
home: Home
14+
categories: Categories
15+
tags: Tags
16+
archives: Archives
17+
about: About
18+
19+
# the text displayed in the search bar & search results
20+
search:
21+
hint: search
22+
cancel: Cancel
23+
no_results: Oops! No results found.
24+
25+
panel:
26+
lastmod: Recently Updated
27+
trending_tags: Trending Tags
28+
toc: Contents
29+
30+
copyright:
31+
# Shown at the bottom of the post
32+
license:
33+
template: This post is licensed under :LICENSE_NAME by the author.
34+
name: CC BY 4.0
35+
link: https://creativecommons.org/licenses/by/4.0/
36+
37+
# Displayed in the footer
38+
brief: Some rights reserved.
39+
verbose: >-
40+
Except where otherwise noted, the blog posts on this site are licensed
41+
under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author.
42+
43+
meta: „Sutor, ne ultra crepidam”
44+
45+
not_found:
46+
statement: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
47+
48+
notification:
49+
update_found: A new version of content is available.
50+
update: Update
51+
52+
# ----- Posts related labels -----
53+
54+
post:
55+
written_by: By
56+
posted: Posted
57+
updated: Updated
58+
words: words
59+
pageview_measure: views
60+
read_time:
61+
unit: min
62+
prompt: read
63+
relate_posts: Further Reading
64+
share: Share
65+
button:
66+
next: Newer
67+
previous: Older
68+
copy_code:
69+
succeed: Copied!
70+
share_link:
71+
title: Copy link
72+
succeed: Link copied successfully!
73+
74+
# Date time format.
75+
# See: <http://strftime.net/>, <https://day.js.org/docs/en/display/format>
76+
df:
77+
post:
78+
strftime: "%b %e, %Y"
79+
dayjs: "ll"
80+
archives:
81+
strftime: "%b"
82+
dayjs: "MMM"
83+
84+
# categories page
85+
categories:
86+
category_measure:
87+
singular: category
88+
plural: categories
89+
post_measure:
90+
singular: post
91+
plural: posts
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
---
2+
title: Tailscale site-to-site pfSense - Linux
3+
date: 2024-04-06 10:00:00 +0200
4+
categories: [Networking, VPN]
5+
tags: [vpn, security, tutorial, tailscale, pfsense]
6+
description: Setting up Tailscale site-to-site connection between pfSense and Linux
7+
image:
8+
path: /assets/img/posts/tailscale-pfsense-banner.webp
9+
alt: Tailscale Site-to-Site VPN Setup
10+
---
11+
12+
I've decided to implement monitoring for my homelab through a cloud virtual machine. As cloud provider I've opted for Hetzner, but more on that in a future post.
13+
14+
To enhance the security of this setup, I've chosen to establish the cloud VM from Hetzner as the single entry point to my infrastructure. For this purpose, I've opted to use Tailscale for tunneling, not only for client-to-site but also for site-to-site connectivity.
15+
16+
## Tailscale Site-to-Site Networking
17+
18+
Information provided by Tailscale:
19+
20+
> Use site-to-site layer 3 (L3) networking to connect two subnets on your Tailscale network with each other. The two subnets are each required to provide a subnet router but their devices do not need to install Tailscale. This scenario applies to Linux subnet routers only.
21+
{: .prompt-info }
22+
23+
> This scenario will not work on subnets with overlapping CIDR ranges, nor with 4via6 subnet routing.
24+
{: .prompt-warning }
25+
26+
## Network Architecture
27+
28+
In my case, there are two private subnets without any connectivity between them:
29+
30+
- **Subnet 1 - Homelab**: 10.57.57.0/24
31+
- **Subnet 2 - Cloudlab**: 192.168.57.0/24
32+
33+
IP addresses of the routers for each subnet:
34+
- **Subnet 1**: 10.57.57.1 (pfSense)
35+
- **Subnet 2**: 192.168.57.254 (Linux VM)
36+
37+
## Setting up Tailscale on pfSense (Subnet I)
38+
39+
Let's dive into the configuration. Due to pfSense being based on FreeBSD and Tailscale not offering as much support for pfSense as for other platforms, this configuration is a bit trickier.
40+
41+
### Install Tailscale on pfSense
42+
43+
1. Navigate to **System > Package Manager** in the pfSense web interface
44+
2. Click on the **Available Packages** tab
45+
3. Search for `tailscale` and click **Install**
46+
47+
### Configure Tailscale on pfSense
48+
49+
Navigate to **VPN > Tailscale**
50+
51+
#### Authentication
52+
53+
1. Copy auth-key from [https://login.tailscale.com/admin/settings/keys](https://login.tailscale.com/admin/settings/keys)
54+
2. Generate Auth keys
55+
56+
![Tailscale pfSense Configuration](/assets/img/posts/blog-tailscale-pfsense.png){: width="700" height="400" }
57+
_Tailscale authentication setup in pfSense_
58+
59+
#### Basic Configuration
60+
61+
-**Enable tailscale**
62+
- **Listen port**: leave as default
63+
-**Accept Subnet Routes**
64+
-**Advertise Exit Node** (optional)
65+
- **Advertised Routes**: 10.57.57.0/24
66+
67+
### Tricky Part: Outbound NAT Rules
68+
69+
Navigate to **Firewall > NAT > Outbound**
70+
71+
#### Configure Outbound NAT Mode
72+
73+
Set to: **Hybrid Outbound NAT**
74+
75+
#### Create Manual Mapping
76+
77+
- **Interface**: Tailscale
78+
- **Address Family**: IPv4+IPv6
79+
- **Protocol**: Any
80+
- **Source Network or Alias**: 10.57.57.0/24
81+
- **Destination**: Any
82+
83+
> This part is broken from last update [23.09.1] so NAT Alias is missing.
84+
{: .prompt-warning }
85+
86+
**Workaround**:
87+
- Translation section:
88+
- **Address**: Network or Alias
89+
- Put the tailscale IP address: `100.xx.xx.xx/32`
90+
91+
This is how it should look:
92+
93+
![Tailscale pfSense NAT Rules](/assets/img/posts/blog-tailscale-pfsense2.png){: width="700" height="400" }
94+
_Outbound NAT configuration for Tailscale_
95+
96+
## Configure Tailscale on Linux VM (Subnet II)
97+
98+
### Install Tailscale and Enable Routing
99+
100+
```bash
101+
# Install tailscale
102+
curl -sSL https://tailscale.com/install.sh | sh
103+
104+
# Activate routing for IPv4
105+
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
106+
107+
# Activate routing for IPv6
108+
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
109+
110+
# Apply routing configuration at kernel level
111+
sudo sysctl -p /etc/sysctl.conf
112+
```
113+
114+
### Advertise Routes on Linux
115+
116+
On the 192.168.57.254 device, advertise routes for 192.168.57.0/24:
117+
118+
```bash
119+
tailscale up --advertise-routes=192.168.57.0/24 --snat-subnet-routes=false --accept-routes
120+
```
121+
122+
**Command explained**:
123+
- `--advertise-routes`: Exposes the physical subnet routes to your entire Tailscale network
124+
- `--snat-subnet-routes=false`: Disables source NAT. In normal operations, a subnet device will see the traffic originating from the subnet router. This simplifies routing, but does not allow traversing multiple networks. By disabling source NAT, the end machine sees the LAN IP address of the originating machine as the source
125+
- `--accept-routes`: Accepts the advertised route of the other subnet router, as well as any other nodes that are subnet routers
126+
127+
## Enable Subnet Routes from Admin Console
128+
129+
> This step is not required if using autoApprovers.
130+
{: .prompt-info }
131+
132+
1. Open the **Machines** page of the admin console
133+
2. Locate the devices configured as subnet routers (look for the **Subnets** badge or use the `property:subnet` filter)
134+
3. For each device, click the ellipsis icon menu and select **Edit route settings**
135+
4. In the Edit route settings panel, approve the device
136+
137+
> The Tailscale side of the routing is complete!
138+
{: .prompt-tip }
139+
140+
## Credits
141+
142+
- [Tailscale Documentation](https://tailscale.com/kb/1214/site-to-site#step-2-enable-subnet-routes-from-the-admin-console) - Official site-to-site networking guide
143+
- [Christian McDonald](https://www.youtube.com/watch?v=Fg_jIPVcioY) - Helpful YouTube tutorial on pfSense Tailscale setup

0 commit comments

Comments
 (0)