1

I have a PC to which a robot is connected via CAN (using SocketCAN). I'd like to control who can send commands to the robot, ideally through a group (i.e. only users who are in the "use_robot" group have permission to send/receive anything via CAN).

How can I achieve this? To my understanding, SocketCAN uses network interfaces so, probably somehow with iptables?

5
  • While I am not positive, the ip in iptables suggests that it won't be particularly useful for CAN networks. Commented Jul 11, 2023 at 0:32
  • Well, the ip command is used to configure the CAN interfaces, so it doesn't seem too unlikely. I'm just not very familiar with iptables, otherwise I would simply give it a try. Commented Jul 11, 2023 at 11:16
  • I did a few tests: using nftables' netdev egress (kernel >= 5.16) it's easy to limit per uid emission. What I don't know how to do is to limit reception. I got a python example to emit traffic through can (python-can.readthedocs.io/en/stable/#python-can), but I don't have anything to listen to traffic to do further testing (who knows? sockets and cgroups?) Commented Jul 11, 2023 at 12:33
  • @A.B For my use case it would actually be enough if I can prevent users from sending something to the robot (as they could potentially damage it). If they can still receive data from the robot, that wouldn't be a problem for me. Commented Jul 11, 2023 at 12:47
  • @A.B you can use cangen and candump from the can-utils project to generate and listen to traffic for testing purposes. Commented Jul 11, 2023 at 13:44

1 Answer 1

2

I'd like to control who can send commands to the robot, ideally through a group...

I spent a little bit of time looking at this today. I can prevent members of a group from sending traffic to a CAN interface using an nftables ruleset like this:

table netdev canfilter {
        chain can1egress {
                type filter hook egress device can1 priority filter; policy accept;
                skgid 1000 counter drop;
        }
}

(The counter in the above ruleset isn't necessary; it just adds a packet count to the output of nft list ruleset.)

This prevents members of group 1000 from sending via the can1 interface. If I try running cangen can1 as a user with gid 1000, I see:

$ sudo -u testuser cangen can1
write: No buffer space available

Whereas if I do the same thing as a user not in that group, it works without errors (and I can receive the traffic using candump on another link).

I think that accomplishes your goal.


I don't think it's possible to limit reception by uid; looking at the logs produced using something like:

table netdev canfilter {
        chain can0ingress {
                type filter hook ingress device can0 priority filter; policy accept;
                log group 0;
        }
}

It looks like on the receiving side we don't have access to the uid/gid metadata (which makes sense, because packets may be arriving from other than the local system).


For testing this out, I used the cangen and candump utilities from the can-utils project, and ulogd for logging since I was using isolated namespaces for the CAN interfaces (so regular kernel logging wasn't an option).


I've streamlined my test and put everything online here.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.