How to duplicate TCP traffic in OpenWrt without affecting existing communication?

Hi everyone,

I need help solving a problem in OpenWrt.

I want to duplicate TCP traffic originating from a device in my local network (e.g., 192.168.1.100) that is sent to an external server (e.g., 203.0.113.10) on port 1883. The goal is to transparently copy this traffic and forward it to another device in my local network (e.g., 192.168.1.200).

It is crucial that the existing communication between 192.168.1.100 and 203.0.113.10 remains unaffected. The devices should not notice any changes, and the duplication process should be completely transparent to both sides.

I attempted to use the dup action in nftables with a rule in the NAT table like this:

nft add rule ip nat prerouting ip saddr 192.168.1.100 ip daddr 203.0.113.10 tcp dport 1883 dup to 192.168.1.200

However, I encountered syntax errors or issues with the functionality. My OpenWrt runs version 23, and the nftables version is 1.0.8.

Is there an alternative method to achieve this in OpenWrt? Perhaps using the tee action?
I would appreciate any solution that keeps the existing routing and communication between the devices intact while duplicating the traffic transparently.

Thanks in advance for your help!

Please post output of

ubus call system board

You know that offloaded traffic will not be duplicated?

tc also has mirroring facility.

Thank you for your response!

Here is the output of ubus call system board:

ubus call system board
{
        "kernel": "5.15.162",
        "hostname": "OpenWrt",
        "system": "ARMv8 Processor rev 4",
        "model": "Xiaomi Mi Router AX3000T (OpenWrt U-Boot layout)",
        "board_name": "xiaomi,mi-router-ax3000t-ubootmod",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "23.05.4",
                "revision": "r24012-d8dd03c46f",
                "target": "mediatek/filogic",
                "description": "OpenWrt 23.05.4 r24012-d8dd03c46f"
        }
}

I understand that offloaded traffic might not be duplicated. My goal is to transparently mirror the traffic from a local device (192.168.1.100) going to an external server (203.0.113.10) to another local device (192.168.1.200) without interfering with the original communication.

Could you please provide more details about how to use tc for this purpose? I'm open to trying the mirroring facility in tc if it can achieve the desired result.

Thank you in advance for your assistance!

You have to re-use fw4 chains or build new table aside

So put this under /etc/nftables.d/ as something.nft

chain mangle_prerouting {
  type filter hook prerouting priority mangle; policy accept;
  ip saddr 192.168.1.100 ip daddr 203.0.113.10 meta l4proto tcp ct original proto-dst 1883 counter dup to 192.168.1.200
}

I added file /etc/nftables.d/inverter_mangle.nft (i updated IPs)

chain mangle_prerouting { type filter hook prerouting priority mangle; policy accept; ip saddr 20.0.0.118 ip daddr 47.110.46.245 meta l4proto tcp ct original proto-dst 1883 counter dup to 20.0.0.5 }

nft -f /etc/nftables.d/inverter_mangle.nft

/etc/nftables.d/inverter_mangle.nft:1:25-25: Error: syntax error, unexpected '{', expecting string or last chain mangle_prerouting { ^ /etc/nftables.d/inverter_mangle.nft:2:3-6: Error: syntax error, unexpected type type filter hook prerouting priority mangle; policy accept; ^^^^ /etc/nftables.d/inverter_mangle.nft:2:48-53: Error: syntax error, unexpected policy type filter hook prerouting priority mangle; policy accept; ^^^^^^ /etc/nftables.d/inverter_mangle.nft:4:1-1: Error: syntax error, unexpected '}' } ^

/etc/init.d/firewall restart

In file included from /dev/stdin:20:2-33: /etc/nftables.d/inverter_mangle.nft:3:98-112: Error: unsupported family ip saddr 20.0.0.118 ip daddr 47.110.46.245 meta l4proto tcp ct original proto-dst 1883 counter dup to 20.0.0.5 ^^^^^^^^^^^^^^^ The rendered ruleset contains errors, not doing firewall restart.

lsmod | grep nft

nf_dup_ipv6            12288  1 nft_dup_ipv6
nf_dup_netdev          12288  2 nft_fwd_netdev,nft_dup_netdev
nf_tables             163840985 nft_fib_inet,nf_flow_table_ipv6,nf_flow_table_ipv4,nf_flow_table_inet,nft_reject_ipv6,nft_reject_ipv4,nft_reject_inet,nft_reject,nft_redir,nft_quota,nft_objref,nft_numgen,nft_nat,nft_masq,nft_log,nft_limit,nft_hash,nft_fwd_netdev,nft_flow_offload,nft_fib_ipv6,nft_fib_ipv4,nft_fib,nft_dup_netdev,nft_dup_ipv6,nft_dup_ipv4,nft_ct,nft_counter,nft_chain_nat
nft_dup_ipv4           12288  0
nft_dup_ipv6           12288  0
nft_dup_netdev         12288  0
root@SoL:/etc/nftables.d# lsmod | grep nft
nf_conntrack           86016  7 nft_redir,nft_nat,nft_masq,nft_flow_offload,nft_ct,nf_nat,nf_flow_table
nf_dup_ipv4            12288  1 nft_dup_ipv4
nf_dup_ipv6            12288  1 nft_dup_ipv6
nf_dup_netdev          12288  2 nft_fwd_netdev,nft_dup_netdev
nf_flow_table          28672  4 nf_flow_table_ipv6,nf_flow_table_ipv4,nf_flow_table_inet,nft_flow_offload
nf_nat                 36864  4 nft_redir,nft_nat,nft_masq,nft_chain_nat
nf_reject_ipv4         12288  2 nft_reject_ipv4,nft_reject_inet
nf_reject_ipv6         12288  2 nft_reject_ipv6,nft_reject_inet
nf_tables             163840985 nft_fib_inet,nf_flow_table_ipv6,nf_flow_table_ipv4,nf_flow_table_inet,nft_reject_ipv6,nft_reject_ipv4,nft_reject_inet,nft_reject,nft_redir,nft_quota,nft_objref,nft_numgen,nft_nat,nft_masq,nft_log,nft_limit,nft_hash,nft_fwd_netdev,nft_flow_offload,nft_fib_ipv6,nft_fib_ipv4,nft_fib,nft_dup_netdev,nft_dup_ipv6,nft_dup_ipv4,nft_ct,nft_counter,nft_chain_nat
nft_chain_nat          12288  2
nft_counter            12288 41
nft_ct                 16384  8
nft_dup_ipv4           12288  0
nft_dup_ipv6           12288  0
nft_dup_netdev         12288  0
nft_fib                12288  3 nft_fib_inet,nft_fib_ipv6,nft_fib_ipv4
nft_fib_inet           12288  0
nft_fib_ipv4           12288  1 nft_fib_inet
nft_fib_ipv6           12288  1 nft_fib_inet
nft_flow_offload       12288  0
nft_fwd_netdev         12288  0
nft_hash               12288  0
nft_limit              12288  5
nft_log                12288  0
nft_masq               12288  1
nft_nat                12288 72
nft_numgen             12288  0
nft_objref             12288  0
nft_quota              12288  0
nft_redir              12288  0
nft_reject             12288  3 nft_reject_ipv6,nft_reject_ipv4,nft_reject_inet
nft_reject_inet        12288  2
nft_reject_ipv4        12288  0
nft_reject_ipv6        12288  0```

You can run fw4 check without restart.

Rename file to anything not .nft
I do not know what is missing in modules for dup syntax exactly copied from nftables manuals.

tc mirred probably works....

I managed to add the rules on OpenWRT after realizing the issue was missing quotes in the command. The correct command is:

bash

Copy code

nft 'add rule ip private mangle_prerouting ip protocol tcp ip saddr 20.0.0.118 ip daddr 47.110.46.245 counter dup to 20.0.0.5'

Current Issue:

  • Packets are copied to 20.0.0.5, but the host cannot process them because they are still addressed to 47.110.46.245.

What I Tried:

  1. Promiscuous Mode: Enabled on 20.0.0.5 but had no effect.
  2. Alias IP: Added 47.110.46.245 to 20.0.0.5 (ip addr add), allowing packets to be received. However, responses interfered with the original communication.
  3. Blocking Responses: Added rules to block responses:
  • iptables -A OUTPUT -s 47.110.46.245 -j DROP
  • ebtables -A OUTPUT -p IPv4 --ip-src 47.110.46.245 -j DROP
  1. Changing Destination IP: Attempted DNAT on the router and Layer 2 MAC translation with ebtables, but this disrupted the original traffic.

Requirement: I need the copied packets to be processed by 20.0.0.5 without interfering with the original communication to the Chinese server (47.110.46.245). Any suggestions? Thank you!

tc mirred works with dsa switch to mirror all traffic.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.