Files
ubicloud/migrate/20230706_add_private_subnet_ipv4.rb
Furkan Sahin 6524645b65 working ipv6 private + ipv4-in-ipv6
This PR introduces a couple of new changes
to support;
1.  Public ipv4: Nat implementation from public to private ipv4.
```
table ip raw {
  chain prerouting {
    type filter hook prerouting priority raw; policy accept;
    ip daddr #{public_ipv4} ip daddr set #{private_ipv4} notrack
    ip saddr #{private_ipv4} ip daddr != 192.168.0.0/16 ip saddr set #{public_ipv4} notrack
  }
}
```
The above rule means;
- If there is a packet coming into public ipv4 address of the VM, we change it
  to private ip. We use stateless nat here since the number of state objects
increasing with the connection count can bring down the whole system to kneel.
- If there is a packet coming out of the VM that is targeted to a public system,
  change the source address of the packet to public ip, if it's destined to
private ipv4, leave it as is, which will be handled by ipsec tunnelling work.
Explained below.

2. Private ipv4: Using dnsmasq dhcp4
This is handled as simple as adding below line to the dnsmasq.conf
```
dhcp-range=tapvm7m86kv,192.168.0.85,192.168.0.85,32
```
We also add the proper routing rules to handle the private ipv4 routing in
between VM <-> tap* <-> namespace NAT/IPsec Tunnelling

3. Private ipv6: Using dnsmasq slaac
 This is handled by adding the below rule to the dnsmasq.conf
 ```
 dhcp-range=tapvm7m86kv,fdfe:62d4:efc4:ef3b::2,fdfe:62d4:efc4:ef3b::2,slaac,64,12h
 ```
Slaac means there will be a router advertisement for the given range and the
mask length. After that, the client figures out its own ip address and adds it
to its networking stack. For this router advertisement to reach to VM, we had to
add the first slice of ipv6 address to the tap* device. Though, the below is
also needed;
```
r "ip -n #{q_vm} addr add #{NetAddr.parse_net(net6).nth(1)}/64 dev tap#{q_vm}"
```
4. Ipsec tunnelling for private ipv6 communication
This was already in place but the rule creation and the addresses needed some
clean-up.
5. Ipsec tunnelling for private ipv4 communication
We added new policy and states to support ipv4 in ipv6 tunnelling. Example end
result for 2 VMs to communicate with each other is the following;
```
root@Ubuntu-2204-jammy-amd64-base /vm/vm7m86kv # ip x p
src 192.168.0.127/32 dst 192.168.0.85/32
	dir fwd priority 0
	tmpl src 2a01:4f8:10a:128b:fc0f:: dst 2a01:4f8:242:4f68:3f93::
		proto esp spi 0x49f55272 reqid 1 mode tunnel
src fdc9:3955:7bf:873c::/64 dst fdfe:62d4:efc4:ef3b::/64
	dir fwd priority 0
	tmpl src 2a01:4f8:10a:128b:fc0f:: dst 2a01:4f8:242:4f68:3f93::
		proto esp spi 0xf567061f reqid 1 mode tunnel
src 192.168.0.85/32 dst 192.168.0.127/32
	dir out priority 0
	tmpl src 2a01:4f8:242:4f68:3f93:: dst 2a01:4f8:10a:128b:fc0f::
		proto esp spi 0x562a887b reqid 1 mode tunnel
src fdfe:62d4:efc4:ef3b::/64 dst fdc9:3955:7bf:873c::/64
	dir out priority 0
	tmpl src 2a01:4f8:242:4f68:3f93:: dst 2a01:4f8:10a:128b:fc0f::
		proto esp spi 0x2ec0170c reqid 1 mode tunnel
root@Ubuntu-2204-jammy-amd64-base /vm/vm7m86kv # ip x s
src 2a01:4f8:10a:128b:fc0f:: dst 2a01:4f8:242:4f68:3f93::
	proto esp spi 0x49f55272 reqid 1 mode tunnel
	replay-window 0
	aead rfc4106(gcm(aes)) 0xf330d5810712412b64fd3f2c7800c15e689010abceea3b85270aa65a9132f9d736f69d32 128
	anti-replay context: seq 0x0, oseq 0x0, bitmap 0x00000000
	sel src 0.0.0.0/0 dst 0.0.0.0/0
src 2a01:4f8:10a:128b:fc0f:: dst 2a01:4f8:242:4f68:3f93::
	proto esp spi 0xf567061f reqid 1 mode tunnel
	replay-window 0
	aead rfc4106(gcm(aes)) 0xf330d5810712412b64fd3f2c7800c15e689010abceea3b85270aa65a9132f9d736f69d32 128
	anti-replay context: seq 0x0, oseq 0x0, bitmap 0x00000000
	sel src ::/0 dst ::/0
src 2a01:4f8:242:4f68:3f93:: dst 2a01:4f8:10a:128b:fc0f::
	proto esp spi 0x562a887b reqid 1 mode tunnel
	replay-window 0
	aead rfc4106(gcm(aes)) 0xc15cd35dbb66ecc5460c9d668c42226ab34ddc1400f4593a539079947f1da9f5b81ed171 128
	anti-replay context: seq 0x0, oseq 0xc, bitmap 0x00000000
	sel src 0.0.0.0/0 dst 0.0.0.0/0
src 2a01:4f8:242:4f68:3f93:: dst 2a01:4f8:10a:128b:fc0f::
	proto esp spi 0x2ec0170c reqid 1 mode tunnel
	replay-window 0
	aead rfc4106(gcm(aes)) 0xc15cd35dbb66ecc5460c9d668c42226ab34ddc1400f4593a539079947f1da9f5b81ed171 128
	anti-replay context: seq 0x0, oseq 0x10f, bitmap 0x00000000
	sel src ::/0 dst ::/0
```
The above outputs mean that for both ip4 and ip6 stack, we check the source and
destination addresses. If they are from a specific private ip4 to specific
private ip6, we use them respectively with public ip6 addresses and setup a
tunnel and send an encrypted packet. Both ends know the keys to encrypt/decrypt
packets.

make tests pass

column rename from private_subnet to net6

rubocop

private_ipv4 arg is added back
This is a temporary measure, will be removed back when the private
networking is in place

even if there is no public ip4, private ip4 works

start using replace instead of add for idempotancy
2023-07-07 13:15:37 +02:00

11 lines
206 B
Ruby

# frozen_string_literal: true
Sequel.migration do
change do
alter_table(:vm_private_subnet) do
add_column :net4, :cidr, null: false
rename_column :private_subnet, :net6
end
end
end