Skip to content

Commit

Permalink
Merge pull request #61 from netfoundry/v0.8.5-release-candidate
Browse files Browse the repository at this point in the history
Added various tc checks and modified -F, --flush operations
  • Loading branch information
r-caamano authored Jul 19, 2024
2 parents 95fd4d3 + 8aaad5b commit e9c9335
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 12 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
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.5] - 2024-07-17

###

- Added code to check if tc qdisc clsact is already enabled on an interface so it there will no longer be
exclusivity errors printed on adding additional filters or re-adding.
- Added code to block entering -b, --outbound_filter if egress tc filter is not applied to the interface first.
- Added code to block duplicate tc ingress / egress filters
- Added code to set outbound filter setting to off for an interface when its tc egress filter is removed.
- Changed operation of -F --flush. Now -F with no additional arguments will remove all entries ingress and egress.
-F -z ingress will remove all ingress filters. -F -z egress will remove all egress filters.

# [0.8.4] - 2024-07-13

###
Expand Down
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ filtering. It can be used in conjunction with ufw's masquerade feature on a WAN
the zfw_outbound_track.o is activated in the egress direction. It can also be used in conjunction with OpenZiti
edge-routers.

## New features -
## New features in 0.8.x -

### Outbound filtering
- This new feature is currently meant to be used in stand alone FW mode (No OpenZiti). It can be run with OpenZiti
Expand All @@ -20,6 +20,23 @@ edge-routers.
there is no need to statically configure high port ranges for return traffic. The assumption is
if you enable inbound ports you want to allow the stateful reply packets for udp and tcp.

An egress filter must be attached to the interface , ```-b, --outbound-filter <ifname>``` needs to be set ,and at least one interface needs to have had an ingress filter applied.

From cli:

```
sudo zfw -X ens33 -O /opt/openziti/bin/zfw_tc_ingress.o -z ingress
sudo zfw -X ens33 -O /opt/openziti/bin/zfw_tc_outbound_track.o -z egress
sudo /opt/openziti/bin/zfw --outbound-filter ens33
```

The above should result in all outbound traffic except for arp and icmp to be dropped on ens33 (icmp echo-reply
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
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 Down Expand Up @@ -478,7 +495,7 @@ sudo zfw --vrrp-enable <ens33 | all> -d
```


### Inserting / Deleting rules
### Inserting / Deleting Ingress rules

The -t, --tproxy-port is has a dual purpose one it to signify the tproxy port used by openziti routers in tproxy mode and the other is to identify either local passthrough with value of 0 and the other is tunnel redirect mode with value of 65535.

Expand All @@ -497,12 +514,24 @@ sudo zfw -I -c 172.16.240.1 -m 32 -o 10.1.1.1 -n 32 -p tcp -l 22 -h 22 -t 0
sudo zfw -D -c 172.16.240.1 -m 32 -o 10.1.1.1 -n 32 -p tcp -l 22
```

- Example: Remove all rule entries from FW
- Example: Remove all rule entries from FW both ingress and egress

```
sudo zfw -F
```

- Example: Remove all ingress rules from FW

```
sudo zfw -F -z ingress
```

- Example: Remove all egress rules from FW

```
sudo zfw -F -z egress
```

### Debugging

Example: Monitor ebpf trace messages
Expand Down
96 changes: 87 additions & 9 deletions src/zfw.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ bool ddos_dport_list = false;
bool service = false;
bool v6 = false;
bool ipv6 = false;
bool ingress = false;
char *service_string;
char *ddos_saddr;
char *ddos_dport;
Expand Down Expand Up @@ -232,7 +233,7 @@ char *object_file;
char *direction_string;
char check_alt[IF_NAMESIZE];

const char *argp_program_version = "0.8.4";
const char *argp_program_version = "0.8.5";
struct ring_buffer *ring_buffer;

__u32 if_list[MAX_IF_LIST_ENTRIES];
Expand Down Expand Up @@ -434,6 +435,52 @@ void ebpf_usage()
}
}

int check_qdisc(char *ifname){
FILE *fp;
char path[2048];
char command[300];
snprintf(command, 300, "/usr/sbin/tc qdisc show dev %s clsact", ifname);
fp = popen(command, "r");
if(!fp){
return 1;
}
int count = 0;
while(fgets(path, sizeof(path), fp) !=NULL){
count++;
}
if(!count){
pclose(fp);
return 1;
}
pclose(fp);
return 0;
}

int check_filter(uint32_t idx, char *direction){
char ifname[IF_NAMESIZE];
if(!if_indextoname(idx, ifname)){
return 1;
}
FILE *fp;
char path[2048];
char command[300];
snprintf(command, 300, "/usr/sbin/tc filter show dev %s %s", ifname, direction);
fp = popen(command, "r");
if(!fp){
return 1;
}
int count = 0;
while(fgets(path, sizeof(path), fp) !=NULL){
count++;
}
if(!count){
pclose(fp);
return 1;
}
pclose(fp);
return 0;
}

/*function to add loopback binding for intercept IP prefixes that do not
* currently exist as a subset of an external interface
* */
Expand Down Expand Up @@ -532,9 +579,11 @@ void set_tc_filter(char *action)
close_maps(1);
}
pid_t pid;
if (!strcmp(action, "add"))
if (!strcmp(action, "add") && check_filter(if_nametoindex(tc_interface),direction_string))
{
set_tc(action);
if(check_qdisc(tc_interface)){
set_tc(action);
}
for (int x = 0; x < 7; x++)
{
char prio[10];
Expand Down Expand Up @@ -577,7 +626,7 @@ void set_tc_filter(char *action)
}
}
}
else
else if(!strcmp(action, "del"))
{
char *const parmList[] = {"/usr/sbin/tc", "filter", action, "dev", tc_interface, direction_string, NULL};
if ((pid = fork()) == -1)
Expand Down Expand Up @@ -1634,7 +1683,13 @@ bool set_diag(uint32_t *idx)
{
if (!disable && *idx != 1)
{
o_diag.outbound_filter = true;
if(!check_filter(*idx,"egress")){
o_diag.outbound_filter = true;
}else{
printf("outbound filter not set no egress filter exists for %s\n", outbound_interface);
printf("set first with: sudo zfw -X %s -O /opt/openziti/bin/zfw_tc_outbound_track.o -z egress\n", outbound_interface);
close_maps(1);
}
}
else
{
Expand Down Expand Up @@ -1812,11 +1867,15 @@ void interface_tc()
{
if (!disable)
{
set_tc("add");
if(check_qdisc(address->ifa_name)){
set_tc("add");
}
}
else
{
set_tc("del");
if(!check_qdisc(address->ifa_name)){
set_tc("del");
}
}
}
if (tcfilter)
Expand All @@ -1835,6 +1894,10 @@ void interface_tc()
else
{
set_tc_filter("del");
if(egress){
outbound = true;
outbound_interface = tc_interface;
}
if (diag_fd == -1)
{
open_diag_map();
Expand Down Expand Up @@ -4675,8 +4738,21 @@ int flush4()

void map_flush()
{
flush4();
flush6();
if(ingress && !egress){
flush4();
flush6();
}else if(!ingress && !egress){
flush4();
flush6();
if(!(access(egress6_map_path, F_OK) != 0)){
egress = true;
flush4();
flush6();
}
}else{
flush4();
flush6();
}
union bpf_attr tp_map;
struct tproxy_extension_key tp_init_key = {0};
struct tproxy_extension_key *tp_key = &tp_init_key;
Expand Down Expand Up @@ -5806,6 +5882,8 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
direction_string = arg;
if(!strcmp("egress", arg)){
egress = true;
}else{
ingress = true;
}
break;
default:
Expand Down

0 comments on commit e9c9335

Please sign in to comment.