3

I have a board sending out two kinds of UDP packets. On the same board I configured a couple of vLANS:

sudo modprobe 8021q 
sudo ip link add link enP2p1s0 name enP2p1s0.5 type vlan id 5 
sudo ip link set enP2p1s0.5 up
sudo ip link add link enP2p1s0 name enP2p1s0.8 type vlan id 8 
sudo ip link set enP2p1s0.8 up

I want to setup the system so that if I send out packets to IP:port1 where port1 value is X, the packet goes out on the VLAN with id 5, and if I send out packets on IP:port2 where IP is the same IP but port2 value is Y - the packet goes out on the VLAN with id 8.

Is this possible?

ilkkachu
  • 138,973
adagan
  • 31
  • 3

3 Answers3

0

Yes You can do so with iptables. You could alter the source address of package (SNAT) to let routing decide for the interface based on IP depneding on the detination port. Or You can set marks dependent on the destination ports, have mutiple routing table and set up ip rules to assign a specific routing table.

  • Thank you for the reply. I am not sure I want to alter the source address of the packages. Can I just set up rules and routing tables so that anything I send out to port X is sent using one vLAN, and everything else goes out on another vLAN? – adagan Nov 13 '19 at 21:25
  • They have to have different source address if there are multiple interfaces (at least the should) so it should be possible. But You can check this link https://serverfault.com/a/389004/543402 . Basically You set up multiple routing tables (using different interfaces for the target IP), make some ip rules and assigne the flags. Or You need the exact example commands step by step? – user301446 Nov 13 '19 at 21:30
  • I appreciate your help. Let me study some more and if I need more hand-holding I will ask. Thanks again. – adagan Nov 13 '19 at 21:40
  • adding two spaces did not add a line :( – adagan Nov 13 '19 at 23:57
  • Yes not possible in comments, sadly. – user301446 Nov 14 '19 at 06:01
0

I think this may work:

sudo ip link add link enP2p1s0 name enP2p1s0.5 type vlan id 5  
sudo ip link set enP2p1s0.5 up  
sudo ip link add link enP2p1s0 name enP2p1s0.8 type vlan id 8  
sudo ip link set enP2p1s0.8 up  
sudo iptables-legacy -A OUTPUT -p udp --dport 15004 -j MARK --set-mark 1  
sudo iptables-legacy -A OUTPUT -p udp --dport 14002 -j MARK --set-mark 2  
sudo ip rule add fwmark 1 table 11  
sudo ip rule add fwmark 2 table 22  
sudo ip route add 192.168.0.0/24 dev enP2p1s0.5 table 11  
sudo ip route add 192.168.0.0/24 dev enP2p1s0.8 table 22

can @EOhm please take a look?

adagan
  • 31
  • 3
  • you must use the mangle table to alter the routing decision. add -t mangle before -A OUTPUT. Also note that return traffic might be filtered by reverse path filtering (use choice 2). then this should work. – A.B Nov 14 '19 at 02:15
  • yes I think the same like @A.B at a quick look. Use mangle table and maybe ensure the rp_filter sysctl is not set to 1. It should work then I think. (Thought don't now now what the -legacy suffix on iptables is for.. – user301446 Nov 14 '19 at 06:01
  • @EOhm on debian 10 by default iptables is using nftables's kernel API. This would prevent it (but this example would have worked the same using nftables' api too). – A.B Nov 14 '19 at 07:49
  • Thank you both. I really appreciate your help. I will report back if this works or not. – adagan Nov 14 '19 at 16:58
0

Thanks again for all inputs. Another answer that was posted (and disappeared?) was this one:

There's also a really exotic method using tc and its vlan action, completely ignoring the network (routing) layer.

Usual preparation: add the simplest classful qdisc (prio) only used here for allowing to attach filters for egress, and add the ingress qdisc:

sudo tc qdisc add dev enP2p1s0 root handle 1: prio
sudo tc qdisc add dev enP2p1s0 ingress

Add filter rules, both ways: tagging for egress, untagging for ingress. u8 at 9 layer network eq 17 means UDP, u16 at 2 layer transport means destination port:

sudo tc filter add dev enP2p1s0 parent 1: protocol ip basic match 'cmp(u8 at 9 layer network eq 17) and cmp(u16 at 2 layer transport eq 15004)' action vlan push id 151
sudo tc filter add dev enP2p1s0 parent 1: protocol ip basic match 'cmp(u8 at 9 layer network eq 17) and cmp(u16 at 2 layer transport eq 14002)' action vlan push id 150
sudo tc filter add dev enP2p1s0 ingress basic match 'meta(vlan eq 150) or meta(vlan eq 151)' action vlan pop

The rest of the network stack will never even be aware of VLANs, because it happens really early (for ingress) and late (for egress).

This approach proved simpler and more robust for my purpose. I had to rebuild the Linux Kernel to support the prio, vlan action, cmp and ingress features (sch_prio, sch_ingress, cls_basic, act_vlan, em_cmp) but so far the solution looks promising.

One note: NICs tend to strip off VLAN tags. That's a real bummer for testing and is a subject for a whole different post/forum

adagan
  • 31
  • 3