Skip to content

Commit

Permalink
Use tc's direct action mode
Browse files Browse the repository at this point in the history
  • Loading branch information
radiantly committed Nov 6, 2022
1 parent fe6b6da commit 8536ded
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 19 deletions.
23 changes: 15 additions & 8 deletions .github/test_udp.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import argparse
import random
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
Expand Down Expand Up @@ -31,27 +32,33 @@ def sendPacket(host):


def main():
if len(sys.argv) != 2:
print("Usage: python test_udp.py SERVER")
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
parser.add_argument("host", help="The host to test")

args = parser.parse_args()

host = gethostbyname(sys.argv[1])
host = gethostbyname(args.host)

rtt = []
failures = 0
with ThreadPoolExecutor(max_workers=WORKERS) as executor:
print(f"Sending {PACKETS_TO_SEND} packets to {host}")
futures = [executor.submit(sendPacket, host) for _ in range(PACKETS_TO_SEND)]

for i, future in enumerate(as_completed(futures)):
for future in as_completed(futures):
result = future.result()
if result == -1:
failures += 1
else:
rtt.append(result)
print(
f"\r{i}/{PACKETS_TO_SEND} packets sent (failures: {failures})", flush=True, end=""
)

if args.verbose:
print(
f"\r{failures + len(rtt)}/{PACKETS_TO_SEND} packets sent (failures: {failures})",
flush=True,
end="",
)

print("\r", end="")
print(plotille.hist(rtt, bins=10))
Expand Down
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
DEVICE=eth0
# If the DEVICE env variable is not set, choose first non-loopback/non-virt interface
DEVICE ?= $(shell ip -br l | awk '$$1 !~ "lo|vir" { print $$1; exit }')

all: qdisc

Expand All @@ -8,13 +9,14 @@ bpf.o: bpf.c
debug: DEBUG = -DDEBUG

debug: all
-sudo tc exec bpf dbg

qdisc-del:
-sudo tc qdisc del dev $(DEVICE) ingress handle ffff:
-sudo tc qdisc del dev $(DEVICE) clsact

qdisc: qdisc-del bpf.o
sudo tc qdisc add dev $(DEVICE) ingress handle ffff: && \
sudo tc filter add dev $(DEVICE) parent ffff: bpf obj bpf.o sec classifier flowid ffff:1 action bpf obj bpf.o sec action ok
sudo tc qdisc add dev $(DEVICE) clsact && \
sudo tc filter add dev $(DEVICE) ingress bpf direct-action obj bpf.o

clean: qdisc-del
-rm bpf.o
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ Visit https://udpquiz.com/ to try it out!
export DEVICE=eth0

# Compile and load
make -e
make

# Once complete, the filter and qdisc can be removed
make -e clean
make clean
```

## References

- [Send ICMP Echo Replies using eBPF](https://fnordig.de/2017/03/04/send-icmp-echo-replies-using-ebpf/)
- [Bypassing Captive Portals](https://blog.chebro.dev/posts/bypassing-captive-portals)
- [tc direct action mode for BPF](https://qmonnet.github.io/whirl-offload/2020/04/11/tc-bpf-direct-action/)
7 changes: 2 additions & 5 deletions bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@

SEC("classifier")
int cls_main(struct __sk_buff *skb) {
return -1;
}

SEC("action")
int act_main(struct __sk_buff *skb) {
/* packet data is stored in skb->data */
void *data = (void *)(long)skb->data;

Expand Down Expand Up @@ -56,6 +51,8 @@ int act_main(struct __sk_buff *skb) {
__be32 src_ip = ip->saddr;
__be32 dst_ip = ip->daddr;

trace_printk("FROM: %d...%d", src_ip & 0xff, src_ip >> 24);

// ignore private ip ranges 10.0.0.0/8, 127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
if ((src_ip & 0xff) == 10 || ((src_ip & 0xff) == 127) || (src_ip & 0xf0ff) == 0x10ac || (src_ip & 0xffff) == 0xa8c0 ||
(dst_ip & 0xff) == 10 || ((dst_ip & 0xff) == 127) || (dst_ip & 0xf0ff) == 0x10ac || (dst_ip & 0xffff) == 0xa8c0)
Expand Down

0 comments on commit 8536ded

Please sign in to comment.