Skip to content

Commit

Permalink
Merge pull request #71 from netfoundry/v0.8.15-release-candidate
Browse files Browse the repository at this point in the history
V0.8.15 release candidate
  • Loading branch information
r-caamano authored Aug 28, 2024
2 parents 72f5ff2 + b88ab99 commit 27dade3
Show file tree
Hide file tree
Showing 10 changed files with 533 additions and 55 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---
###
# [0.8.15] - 2024-08-26
- Refactored all startup scripts to default InternalInterfaces to have outbound tracking enabled
- Refactored IPv4 masquerade to use dynamic PAT vs static PAT and added RB logging
- Fixed issue where if IPv4 udp checksum was 0 masquerade erroneously attempted to recalculate the checksum



###
# [0.8.14] - 2024-08-16
- Fixed issue where icmp type 3 tcp only accepting inbound for ports associated with local listening ports
Expand Down
24 changes: 11 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ EBPF based masquerade capability for both IPv4/IPv6.

### Native EBPF based IPv4 and IPv6 Masquerade support

zfw can now provide native IPv4/IPv6 masquerade operation for outbound pass through connections which can be enabled via:
zfw can now provide native IPv4/IPv6 masquerade operation for outbound pass through connections which can be enabled on a WAN facing interface:

```sudo zfw -k, --masquerade <ifname>```

This function requires that both ingress and egress TC filters are enabled on outbound interface.
This function requires that both ingress and egress TC filters are enabled on outbound interface. For IPv4 this is now using Dynamic PAT and IPv6 is using
static PAT. Note: When running on later kernels i.e. 6+ some older network hardware may not work with ebpf Dynamic PAT.

### Explicit Deny Rules
This feature adds the ability to enter explicit deny rules by appending ```-d, --disable to the -I, --insert rule``` to both ingress and egress rules. Rule precedence is based on longest match prefix. If the prefix is the same then the precedence follows the order entry of the rules, which when listed will go from top to bottom for ports with in the same prefix e.g.
Expand Down Expand Up @@ -97,8 +98,7 @@ The above should result in all outbound traffic except for arp and icmp to be dr
will also be dropped unless ```sudo zfw -e ens33 is set```). ssh return traffic will also be allowed outbound
unless ```ssh -x ens33 is set```.

In order to survive reboot you must have "OutboundPassThroughTrack": true which is default for ExternalInterfaces
but can also be explicitly set for InternalInterfaces. If per interface rules is not false then the egress rules would
If per interface rules is not false then the egress rules would
need explicit -N <interface name added> for each rule in the same manner as ingress rules.

i.e. set ```/opt/openziti/etc/ebpf_config.json``` as below changing interface name only
Expand All @@ -107,7 +107,7 @@ i.e. set ```/opt/openziti/etc/ebpf_config.json``` as below changing interface na

or equivalent InternalInterfaces config:

```{"InternalInterfaces":[{"Name":"ens33", "OutboundPassThroughTrack": true}],"ExternalInterfaces":[]}```
```{"InternalInterfaces":[{"Name":"ens33"}],"ExternalInterfaces":[]}```

Then in executable script file ```/opt/openziti/bin/user/user_rules.sh```
```
Expand Down Expand Up @@ -184,7 +184,7 @@ Rule Count: 1
- *Supports inbound ssh (Can be disabled via ```sudo zfw -x <ifname | all>```) (Care should be taken as this affects IPv4 as well)
- Supports outbound stateful host connections (Inbound only if outbound initiated)
- Supports outbound passthrough tracking. Sessions initiated from non-ebpf enabled and ebpf enabled internal interfaces out
through interface(s) defined as ExternalInterface or with "OutboundPassThroughTrack": true in /opt/openziti/etc/ebpf_config.json
through interface(s) defined as ExternalInterface (requires -N <iface-name> with -I unless "PerInterfaceRules": false) or InternalInterface in /opt/openziti/etc/ebpf_config.json
or manually applied with sudo ```zfw -X <ifname> -O /opt/openziti/zfw_outbound_track.o -z egress```
will allow stateful udp and tcp session traffic back in.
- Support for inbound IPv6 filter destination rules. Currently only destination filtering is allowed.
Expand Down Expand Up @@ -281,10 +281,9 @@ sudo cp /opt/openziti/etc/ebpf_config.json.sample /opt/openziti/etc/ebpf_config.
sudo vi /opt/openziti/etc/ebpf_config.json
```
- Adding interfaces
Replace ens33 in line with:{"InternalInterfaces":[{"Name":"ens33" ,"OutboundPassThroughTrack": false, "PerInterfaceRules": false}], "ExternalInterfaces":[]}
Replace ens33 in line with:{"InternalInterfaces":[{"Name":"ens33"}], "ExternalInterfaces":[]}
Replace with interface that you want to enable for ingress firewalling / openziti interception and
optionally ExternalInterfaces if running containers or other subtending devices (Described in more detail
later in this README.md).
optionally ExternalInterfaces if you want per interface rules -N <iface-name> with -I.
```
i.e. ens33
{"InternalInterfaces":[{"Name":"ens33"}], "ExternalInterfaces":[]}
Expand Down Expand Up @@ -425,15 +424,14 @@ sudo zfw -X ens33 -O /opt/openziti/bin/zfw_tc_outbound_track.o --direction egres
sudo vi /opt/openziti/etc/ebpf_config.json
```
```
{"InternalInterfaces":[{"Name":"ens37","OutboundPassThroughTrack": false, PerInterfaceRules: false}],
{"InternalInterfaces":[{"Name":"ens37","OutboundPassThroughTrack": true, PerInterfaceRules: false}],
"ExternalInterfaces":[{"Name":"ens33", OutboundPassThroughTrack: true, PerInterfaceRules: true}]}
```
The above JSON sets up ens33 to be an internal interface (No outbound tracking) and ens33 as an external interface
with outbound tracking (Default for External Interface). It also automatically adds runs the sudo zfw -P ens33 so ens33
(default for ExternalInterfaces) which requires -N to add inbound rules to it and will ignore rules where it is not in the interface list.
Keys "OutboundPassThroughTrack" and "PerInterfaceRules" are shown with their default values, you only need to add them if you
want change the default operation for the interface type. Note: if ebpf is enabled on an interface before it has ip address assigned a rule assigned
with that interface name and -N it will not show up until at least one diag command is toggled or ebpf is disabled and re-enabled on it via -X, --set-tc-filter.
want change the default operation for the interface type.

#### Single Interface config with ens33 facing lan local lan
```
Expand Down Expand Up @@ -470,7 +468,7 @@ source of the L2tpv3 tunnel on each zet host needs to be set to the ip address a
interface which will be the first host address in the ZITI_DNS_IP_RANGE. In addition you will need to enable
ebpf outbound tracking on the loopback interface. This can be setup vi /opt/openziti/etc/ebpf_config.json i.e.
```
{"InternalInterfaces":[{"Name":"eth0", "OutboundPassThroughTrack": false, "PerInterfaceRules": false}, {"Name":"lo", "OutboundPassThroughTrack": true}],"ExternalInterfaces":[]}
{"InternalInterfaces":[{"Name":"eth0"}, {"Name":"lo", "OutboundPassThroughTrack": true}],"ExternalInterfaces":[]}
```

### Ziti Edge Tunnel Bidirectional Transparency (zfw-tunnel only)
Expand Down
2 changes: 1 addition & 1 deletion files/json/ebpf_config.json.sample
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{"InternalInterfaces":[{"Name":"ens33", "OutboundPassThroughTrack": false, "PerInterfaceRules": false}],
{"InternalInterfaces":[{"Name":"ens33", "OutboundPassThroughTrack": true, "PerInterfaceRules": false}],
"ExternalInterfaces":[]}
2 changes: 1 addition & 1 deletion files/scripts/start_ebpf_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def set_local_rules(ip):
else:
outbound_passthrough_track[interface["Name"]] = False;
else:
outbound_passthrough_track[interface["Name"]] = False;
outbound_passthrough_track[interface["Name"]] = True;
if("PerInterfaceRules") in interface.keys():
if(interface["PerInterfaceRules"]):
per_interface_rules[interface["Name"]] = True;
Expand Down
2 changes: 1 addition & 1 deletion files/scripts/start_ebpf_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ def set_local_rules(resolver):
else:
outbound_passthrough_track[interface["Name"]] = False;
else:
outbound_passthrough_track[interface["Name"]] = False;
outbound_passthrough_track[interface["Name"]] = True;
if("PerInterfaceRules") in interface.keys():
if(interface["PerInterfaceRules"]):
per_interface_rules[interface["Name"]] = True;
Expand Down
2 changes: 1 addition & 1 deletion files/scripts/start_ebpf_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def tc_status(interface, direction):
else:
outbound_passthrough_track[interface["Name"]] = False;
else:
outbound_passthrough_track[interface["Name"]] = False;
outbound_passthrough_track[interface["Name"]] = True;
if("PerInterfaceRules") in interface.keys():
if(interface["PerInterfaceRules"]):
per_interface_rules[interface["Name"]] = True;
Expand Down
45 changes: 41 additions & 4 deletions src/zfw.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
#define CLIENT_INITIATED_ICMP_ECHO 29
#define IP6_HEADER_TOO_BIG 30
#define IPV6_TUPLE_TOO_BIG 31
#define REVERSE_MASQUERADE_ENTRY_REMOVED 32
#define MASQUERADE_ENTRY_REMOVED 33
#define REVERSE_MASQUERADE_ENTRY_ADDED 34
#define MASQUERADE_ENTRY_ADDED 35

bool ddos = false;
bool add = false;
Expand Down Expand Up @@ -218,6 +222,7 @@ const char *egress6_map_path = "/sys/fs/bpf/tc/globals/zt_egress6_map";
const char *egress_count_map_path = "/sys/fs/bpf/tc/globals/egress_count_map";
const char *egress_count6_map_path = "/sys/fs/bpf/tc/globals/egress6_count_map";
const char *masquerade_map_path = "/sys/fs/bpf/tc/globals/masquerade_map";
const char *masquerade_reverse_map_path = "/sys/fs/bpf/tc/globals/masquerade_reverse_map";
const char *icmp_masquerade_map_path = "/sys/fs/bpf/tc/globals/icmp_masquerade_map";
const char *icmp_echo_map_path = "/sys/fs/bpf/tc/globals/icmp_echo_map";
char doc[] = "zfw -- ebpf firewall configuration tool";
Expand All @@ -241,7 +246,7 @@ char *direction_string;
char *masq_interface;
char check_alt[IF_NAMESIZE];

const char *argp_program_version = "0.8.14";
const char *argp_program_version = "0.8.15";
struct ring_buffer *ring_buffer;

__u32 if_list[MAX_IF_LIST_ENTRIES];
Expand Down Expand Up @@ -657,15 +662,15 @@ void disable_ebpf()
disable = true;
tc = true;
interface_tc();
const char *maps[36] = {tproxy_map_path, diag_map_path, if_map_path, count_map_path,
const char *maps[37] = {tproxy_map_path, diag_map_path, if_map_path, count_map_path,
udp_map_path, matched_map_path, tcp_map_path, tun_map_path, if_tun_map_path,
transp_map_path, rb_map_path, ddos_saddr_map_path, ddos_dport_map_path, syn_count_map_path,
tp_ext_map_path, if_list_ext_map_path, range_map_path, wildcard_port_map_path, tproxy6_map_path,
if6_map_path, count6_map_path, matched6_map_path, egress_range_map_path, egress_if_list_ext_map_path,
egress_ext_map_path, egress_map_path, egress6_map_path, egress_count_map_path, egress_count6_map_path,
egress_matched6_map_path, egress_matched_map_path, udp_ingress_map_path, tcp_ingress_map_path,
masquerade_map_path, icmp_masquerade_map_path, icmp_echo_map_path};
for (int map_count = 0; map_count < 36; map_count++)
masquerade_map_path, icmp_masquerade_map_path, icmp_echo_map_path, masquerade_reverse_map_path};
for (int map_count = 0; map_count < 37; map_count++)
{

int stat = remove(maps[map_count]);
Expand Down Expand Up @@ -3109,6 +3114,22 @@ static int process_events(void *ctx, void *data, size_t len)
{
state = "MATCHED_DROP_FILTER";
}
else if (code == REVERSE_MASQUERADE_ENTRY_ADDED)
{
state = "REVERSE_MASQUERADE_ENTRY_ADDED";
}
else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED)
{
state = "REVERSE_MASQUERADE_ENTRY_REMOVED";
}
else if (code == MASQUERADE_ENTRY_ADDED)
{
state = "MASQUERADE_ENTRY_ADDED";
}
else if (code == MASQUERADE_ENTRY_REMOVED)
{
state = "MASQUERADE_ENTRY_REMOVED";
}

if (state)
{
Expand Down Expand Up @@ -3447,6 +3468,22 @@ static int process_events(void *ctx, void *data, size_t len)
{
state = "MATCHED_DROP_FILTER";
}
else if (code == REVERSE_MASQUERADE_ENTRY_ADDED)
{
state = "REVERSE_MASQUERADE_ENTRY_ADDED";
}
else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED)
{
state = "REVERSE_MASQUERADE_ENTRY_REMOVED";
}
else if (code == MASQUERADE_ENTRY_ADDED)
{
state = "MASQUERADE_ENTRY_ADDED";
}
else if (code == MASQUERADE_ENTRY_REMOVED)
{
state = "MASQUERADE_ENTRY_REMOVED";
}


if (state)
Expand Down
38 changes: 37 additions & 1 deletion src/zfw_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
#define CLIENT_INITIATED_ICMP_ECHO 29
#define IP6_HEADER_TOO_BIG 30
#define IPV6_TUPLE_TOO_BIG 31
#define REVERSE_MASQUERADE_ENTRY_REMOVED 32
#define MASQUERADE_ENTRY_REMOVED 33
#define REVERSE_MASQUERADE_ENTRY_ADDED 34
#define MASQUERADE_ENTRY_ADDED 35

bool logging = false;
bool monitor = false;
Expand All @@ -81,7 +85,7 @@ char check_alt[IF_NAMESIZE];
char doc[] = "zfw_monitor -- ebpf firewall monitor tool";
const char *rb_map_path = "/sys/fs/bpf/tc/globals/rb_map";
const char *tproxy_map_path = "/sys/fs/bpf/tc/globals/zt_tproxy_map";
const char *argp_program_version = "0.8.14";
const char *argp_program_version = "0.8.15";
union bpf_attr rb_map;
int rb_fd = -1;

Expand Down Expand Up @@ -510,6 +514,22 @@ static int process_events(void *ctx, void *data, size_t len)
{
state = "MATCHED_DROP_FILTER";
}
else if (code == REVERSE_MASQUERADE_ENTRY_ADDED)
{
state = "REVERSE_MASQUERADE_ENTRY_ADDED";
}
else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED)
{
state = "REVERSE_MASQUERADE_ENTRY_REMOVED";
}
else if (code == MASQUERADE_ENTRY_ADDED)
{
state = "MASQUERADE_ENTRY_ADDED";
}
else if (code == MASQUERADE_ENTRY_REMOVED)
{
state = "MASQUERADE_ENTRY_REMOVED";
}

if (state)
{
Expand Down Expand Up @@ -848,6 +868,22 @@ static int process_events(void *ctx, void *data, size_t len)
{
state = "MATCHED_DROP_FILTER";
}
else if (code == REVERSE_MASQUERADE_ENTRY_ADDED)
{
state = "REVERSE_MASQUERADE_ENTRY_ADDED";
}
else if (code == REVERSE_MASQUERADE_ENTRY_REMOVED)
{
state = "REVERSE_MASQUERADE_ENTRY_REMOVED";
}
else if (code == MASQUERADE_ENTRY_ADDED)
{
state = "MASQUERADE_ENTRY_ADDED";
}
else if (code == MASQUERADE_ENTRY_REMOVED)
{
state = "MASQUERADE_ENTRY_REMOVED";
}


if (state)
Expand Down
Loading

0 comments on commit 27dade3

Please sign in to comment.