Should DHCP discover 0.0.0.0:68->255.255.255.255:67 be allowed in the Router?

You're absolutely correct that DHCP servers use raw sockets on both receive and transmit. The main reason, however, is not the interface restriction.

The main reason is that most DHCP servers want to respond to a client in a unicast packet, which is unicast in the MAC address sense, but not in the IP sense. As you have correctly identified, it is only possible to generate this packet from a raw socket (or a bit more correctly: impossible to generate from a normal POSIX socket). But the important part is this: in order to generate this packet (in any way) you have to know the MAC address to send it to, which, had you received the original packet on a POSIX UDP socket, you would be not be aware of.

Nice to read so many helpful and informative answers!
Rule was already changed form action=accept to action=passthrough without any issue (as per use of RAW socket)

Thanks @CGGXANNX and everyone contributed sharing their knowledge, you're making MikroTik forum a wonderful place where to learn everyday something new!

1 Like

DHCPv6 on RouterOS does not use the raw sockets, only the normal sockets, thus does not bypass the firewall. Here I'm talking only about DHCPv6, not about Router Advertisement / Neighbor Discovery Protocol / SLAAC!

  • When acting als DHCPv6 server, it listens on UDP port 547. If it wants to receive and process requests from clients, then the firewall must allow the UDP packets to arrive on UDP port 547 on the input chain. If there are firewall rules preventing this, then it won't work.

    In a configuration based on the defconf firewall, then normally you don't have to add any special rules for this. Because in that default configuration, incoming connections / packets from the interfaces in the LAN list to the input are allowed (the drop rule on the input chain acts on in-interface-list=!LAN), and normally you would probably only want to serve DHCPv6 clients coming from those interfaces (by configuring DHCPv6 server instances on those interfaces and adding IPv6 -> ND entries on them with the Managed Address Configuration flag turned on).

  • When acting als DHCPv6 client, then the router normally opens a socket on UDP port 546 on the chosen interface, to send and receive packets. In a "normal" configuration this interface is usually considered to be WAN side, and there would normally be firewall rules blocking new connections to the input chain from this side (for example in the defconf firewall, this is the case).

    When acting as DHCPv6 client, it's normally the router that initiates the communication by sending out packets. So we may probably think that nothing unusual needs to be configured on the firewall, because normally the firewall would have a rule that accepts response packets (the "established,related" rule).

    But that's not the case for the DHCPv6 client. Because when it first tries to discover remote DHCPv6 servers, it sends solicit UDP packets from port 546 to port 547 of the destination address ff02::1:2. This is a multicast address, representing all DHCP servers and relay agents. However, when a remote server responds to this (with the advertise message), it will send a packet with the source address being the unicast address of the server (usually a link-local address, but it can also be a non-link-local address!) which is NOT ff02::1:2.

    When this packet arrives at the DHCPv6 client (the router), connection tracking will not be able to associate this packet with the initial solicit message (because the source address is not ff02::1:2). To the router, this is a packet of a new connection.

    In a typical configuration where new connections are not allowed from the WAN side, this obviously won't work. That's why if you look at the defconf firewall rules, you can see this rule being added:

    /ipv6 firewall filter
    add chain=input action=accept protocol=udp dst-port=546 src-address=fe80::/10 \
        comment="defconf: accept DHCPv6-Client prefix delegation.
    

    and it placed before the "defconf: drop everything else not coming from LAN" rule of the input chain. In short, in coming connections to UDP port 546 must be allowed on the input chain.

    If you look at that defconf rule, you can see that MikroTik has also placed a src-address=fe80::/10 restriction. This means that it assumes that the DHCPv6 server (or relay) is located on the same link-layer and uses its link-local address as source in the advertise packet. Most of the time this is the case, and this rule works. However, there are ISPs where their DHCPv6 server might use a global unicast address (GUA) as source when sending DHCPv6 messages to the clients. In this case, this rule won't work, and normally as workaround the src-address=fe80::/10 has to be removed from the rule (which make the rule somewhat less safe).

    After this advertise packets, the other exchange between the client and server (request and reply messages) will be part of a tracked established connection. Please note that there can be multiple different servers that respond to solicit by sending advertise, the client just needs to pick one of them to send the request message to.

Well, actually the MAC address of the client is also duplicated within the DHCP DISCOVER packet. So that would not be an issue.

Furthermore, with UDP sockets there is also the “cmsg” feature that lets you retrieve all kinds of header info that would not normally be available when just reading datagrams from a socket fd. I used that in one of my programs to obtain the IP addresses for packets received on a socket bound to 0.0.0.0. I’m not sure if the link level (MAC) addresses are in there as well.