Firewall - nftables blocks outbound traffic - firewall

I've got a VM at a hosting service and installed a basic firewall with nftables.
However, when it is active, all outbound traffic seems to get blocked. For example, when trying to ping google.com, I get a No route to host error. This occurs for any host I try to ping.
Here's my (really basic) config:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# allow connection from loopback
iifname lo accept;
# established/related connections
ct state {established, related} accept;
# drop invalid connections
ct state invalid drop;
# allow ping
ip protocol icmp icmp type echo-request accept;
icmpv6 type echo-request accept;
# allow ssh connection on port 22
tcp dport 22 accept;
log flags all;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
I just cannot figure out where my problem lies.

Related

How to set up a RaspberryPi & Nftables for masquerading between to interfaces?

I'm trying to set up a RaspberryPi running Nftables as a "router". It's running on RaspberryPi OS 64 bits with kernel 5.15.32-v8+ and Nftables v0.9.8 (E.D.S.). I would like it to allow traffic between the LAN it's connected to through its WiFi interface and an Android phone sharing it's cellular data connection through USB.
The RPi is connected to a LAN through it's WiFi interface. There is a DHCP server running on that LAN. It serves clients class C private addresses like 192.168.80.X/24. The RaspberryPi gets served as below. The network configuration allows for a range of IP addresses to be assigned manually, shall that be needed.
- RaspberryPi : interface wlan0
- IP address : 192.168.80.157
- Subnet : 255.255.255.0
- Gateway : 192.168.80.2
- DNS : 192.168.200.1 (firewall living an another VLAN) / 8.8.8.8
An Android phone is connected to the RaspberryPi through a USB cable and acts as a USB modem, sharing its cellular data. It assigns the RPi a class C private address like 192.168.X.Y/24. It changes each time I plug the Android phone in / reboot, and I can't tune the range of addresses served by the phone.
- RaspberryPi : interface usb0 (Android phone)
- IP address : 192.168.42.48 (at the moment)
- Subnet : 255.255.255.0
- Gateway : 192.168.42.105
- DNS : 192.168.42.105 (same as gateway)
I have enabled IP forwarding in the sysctl.conf
net.ipv4.ip_forward=1
Nftables is configured as follow (example from here :
table ip nat_antoine {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
ip protocol icmp counter meta nftrace set 1
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "usb0" masquerade
}
}
I ran the following tests. I disabled nftables and SSH'd into the RPi through the wlan0 interface. If I configure the firewall at 192.168.200.1 to allow internet access to the RPi (and disconnect the Android phone "usb0"), it works : the RPi can ping / curl / ssh into the "outside" world.
Then I revoked the internet access through wlan0 and plugged the Android phone "usb0" in. Same : I can ping / curl / ssh into the "outside" world. I have made sure that the traffic is going through usb0 and not wlan0.
Issues arise when I enable nftables and try to access internet via the RPi through another client. I took another android phone, connected it to the 192.168.80.0/24 LAN and manually configured the gateway address to be the RPi's wlan0 interface address (DNS from Quad9). Best I can get is pinging the wlan0 interface on the RPi.
"nft monitor" output when pinging 192.168.80.157 from an Android client (client gets an answer) :
trace id 98bebc6f ip nat_antoine prerouting packet: iif "wlan0" ether saddr d0:1b:49:f1:01:29 ether daddr dc:a6:32:65:a2:f4 ip saddr 192.168.80.20 ip daddr 192.168.80.157 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 40158 ip length 84 icmp code net-unreachable icmp id 30 icmp sequence 1 #th,64,96 820786881435526521749372928
trace id 98bebc6f ip nat_antoine prerouting rule ip protocol icmp counter packets 1 bytes 84 meta nftrace set 1 (verdict continue)
trace id 98bebc6f ip nat_antoine prerouting verdict continue
trace id 98bebc6f ip nat_antoine prerouting policy accept
"nft monitor" output when pinging 192.168.42.48 from the same Android client (client gets no answer) :
trace id c59a6b89 ip nat_antoine prerouting packet: iif "wlan0" ether saddr d0:1b:49:f1:01:29 ether daddr dc:a6:32:65:a2:f4 ip saddr 192.168.80.20 ip daddr 192.168.42.48 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 29620 ip length 84 icmp code net-unreachable icmp id 31 icmp sequence 1 #th,64,96 56218603639456293821148039936
trace id c59a6b89 ip nat_antoine prerouting rule ip protocol icmp counter packets 1 bytes 84 meta nftrace set 1 (verdict continue)
trace id c59a6b89 ip nat_antoine prerouting verdict continue
trace id c59a6b89 ip nat_antoine prerouting policy accept
Can someone please help me / point me to the right direction for fixing this ?
Thank you very much.

What does wg-quick nftables rules do?

When I add a wireguard interface via wg-quick up wg0, wg-quick sets up the following nftable rules. What are these doing and why are they needed?
Here are some example rules for ipv4:
table ip wg-quick-wg0 {
chain preraw {
type filter hook prerouting priority raw; policy accept;
iifname != "wg0" ip daddr 10.4.125.231 fib saddr type != local drop
}
chain premangle {
type filter hook prerouting priority mangle; policy accept;
meta l4proto 17 meta mark set ct mark
}
chain postmangle {
type filter hook postrouting priority mangle; policy accept;
meta l4proto 17 meta mark 0x0000ca6c ct mark set meta mark
}
}
I am interested in these, because my virtual machine needs those to function properly, but my host does not need them to have a working wireguard interface. Sadly the script itself is not documented on why they are setup.
The wg-quick script sets up these rules only when you configure the AllowedIPs of a WireGuard peer to include /0 -- aka "all addresses" or the "default route" for an address family (0.0.0.0/0 for IPv4 and ::/0 for IPv6).
Using a tunnel like WireGuard for a default route requires some tricks to work correctly in most scenarios. The main trick wg-quick uses is to put the new default route into a custom routing table, while adding policy routing rules with a firewall mark to overide only the default route of the main table. This is the purpose for the route and policy rules you'll see wg-quick set up in this case:
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
The firewall rules listed in your question help with a few additional edge cases: The first rule prevents certain routing loops and other issues when packets are sent to the WireGuard interface's address outside of the tunnel; and the second and third rules fix up reverse-path lookups for packets received through the tunnel (allowing reverse-path filtering to work).
If you don't want wg-quick to do these things, you can set Table = off in the [Interface] section of your WireGuard configuration, and set up the appropriate routes yourself. For more details about these routing tricks, see the Routing All Your Traffic section of the routing guide on the WireGuard site, or the Understanding Modern Linux Routing article. See the Wg-quick Default Firewall Rules article for more details about these firewall rules specifically.

IPTABLES redirect specific wan traffic back to another address on wan

What i am trying to achieve with iptables is setting a rule(s) that when a specific packet arrives from wan it gets redirected to a new address on wan.
Example:
Any UDP packet arriving on port 10000 gets redirected to 8.8.8.8:10000.
This can be more specific, like it originates from ip 1.1.1.1 or destination lan ip is 192.168.1.1 if there is a requirement for the rule to work.
Is this possible? Been trying a couple of rules in chain PREROUTING and using DNAT but i'm honestly in the dark here...
First: your question is more appropriate at Server Fault or Unix & Linux.
To answer your question: it isn't sufficient to only change the destination address because all returned datagrams would go directly from 8.8.8.8 to the original sender who could not relate them to the original datagrams.
So you would add DNAT rules in the PREROUTING chain and additional SNAT rules in the POSTROUTING chain so that the answers gets back to your machine and then can be sent back to the original sender with the appropriate addresses. You have to be very careful when designing these rules.

How to make google cloud's wordpress template accessible to the public?

I deployed a VM with wordpress already installed and I was able to access initially. It appears that after some time web traffic is blocked if using the external IP address.
I tried allowing http/https from the google admin dashboard as well as adding those rules to IPTABLES in the debian instance but I'm still unable to access when using the external IP address.
Here is my IPTABLE -L output:
root#wordpress-2-vm:/home/myname# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/NONE
DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN state NEW
DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,PSH,ACK,URG
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:https

Fields in ip/tcp header required to be changed when data is modified in an IP packet

This is an extension to my other question- modifying ip packet using libipq
I have a linux bridge set up between a client and a server machine. I forward the tcp packets coming from the server to the client during I modify data in certain packets. I am calculating the new checksum on the packets that I modify. The packets that are unmodified get forwarded properly whereas the packets that I modify are not getting forwarded to the client. I am using the following statement to accept and forward the packet after I modify the packet:
ipq_set_verdict (h, m->packet_id, NF_ACCEPT, m->data_len, m->payload);
My iptable rule is"
iptables -A OUTPUT -p tcp -j QUEUE
Any help how I can overcome this?

Resources