EBTABLES(8)

๐Ÿ“ฆ
version 1.8.13 ยท 6 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, debian trixie, fedora 43, fedora 44, nixpkgs unstable, opensuse-leap 16.0, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– EBTABLES(8): ebtables, the bestie manual ๐Ÿ’–

System Manager's Manual ๐ŸŽ€

๐ŸŒธ NAME ๐ŸŒธ

ebtables โ€” Ethernet bridge frame table administration (nft-based) โœจ

๐Ÿงš SYNOPSIS ๐Ÿงš

ebtables [-t table ] -[ACDI] chain rule specification [match extensions]
[watcher extensions] target
ebtables [-t table ] -P chain ACCEPT | DROP | RETURN
ebtables [-t table ] -F [chain]
ebtables [-t table ] -Z [chain]
ebtables [-t table ] -L [-Z] [chain] [ [--Ln] | [--Lx] ] [--Lc]
[--Lmac2]
ebtables [-t table ] -N chain [-P ACCEPT | DROP | RETURN]
ebtables [-t table ] -X [chain]
ebtables [-t table ] -E old-chain-name new-chain-name
ebtables [-t table ] --init-table

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so ebtables is an application program that lets you set up and maintain the tables of rules (living inside the Linux kernel) that inspect Ethernet frames ๐Ÿ’… It's basically the iptables energy, but way less complicated, because Ethernet is a much simpler protocol than IP ๐Ÿซถ

โœจ CHAINS โœจ

there are three ebtables tables with built-in chains in the Linux kernel ๐Ÿ‘‘ they're used to split functionality into different sets of rules, and each set of rules is called a chain. each chain is an ordered list of rules that can match Ethernet frames. if a rule matches a frame, then a processing specification tells what to do with that matching frame, and that processing specification is called a 'target'. but if the frame doesn't match the current rule, the next rule in the chain gets checked, and so forth ๐Ÿ”ฅ users can also create new (user-defined) chains that can be used as the 'target' of a rule. user-defined chains are super useful for getting better performance over the linear traversal of the rules, and they're also essential for structuring filtering rules into well-organized, maintainable sets ๐ŸŽ€

๐ŸŽฏ TARGETS ๐ŸŽฏ

a firewall rule specifies criteria for an Ethernet frame plus a frame processing specification called a target ๐Ÿ’œ when a frame matches a rule, the next action the kernel performs is whatever the target says. the target can be one of these values: ACCEPT, DROP, CONTINUE, RETURN, an 'extension' (see below), or a jump to a user-defined chain.

ACCEPT means let the frame through โœจ DROP means the frame has to be dropped ๐Ÿ’€ BUT in the BROUTING chain, ACCEPT and DROP mean different things (see the info provided for the -t option, it's a whole thing). CONTINUE means the next rule has to be checked, which is handy, f.e., to know how many frames pass a certain point in the chain, to log those frames, or to apply multiple targets on a frame ๐Ÿ“Š RETURN means stop traversing this chain and resume at the next rule in the previous (calling) chain ๐ŸŒˆ for the extension targets, please refer to the TARGET EXTENSIONS section of this man page ๐Ÿซถ

๐Ÿ“ TABLES ๐Ÿ“

as we said earlier, the table names are filter, nat and broute ๐Ÿ’… of these, the filter table is the default one the command operates on. if you're working with a table other than filter, you'll need to provide the -t argument. also, if you use -t, it has to be the very first argument on the ebtables command line, no exceptions bestie ๐Ÿ™ˆ

  • -t, --table โ€” this is where you pick your table, and each one has its own vibe:
    • filter is the default table and has three built-in chains: INPUT (for frames destined for the bridge itself, on the level of the MAC destination address), OUTPUT (for locally-generated or (b)routed frames) and FORWARD (for frames being forwarded by the bridge) ๐ŸŒธ
    • nat is mostly used to change MAC addresses and has three built-in chains: PREROUTING (for altering frames as soon as they come in), OUTPUT (for altering locally generated or (b)routed frames before they're bridged) and POSTROUTING (for altering frames as they're about to go out) ๐Ÿฆ‹ small note on the naming of PREROUTING and POSTROUTING: technically it'd be more accurate to call them PREFORWARDING and POSTFORWARDING, but for everyone coming from the iptables world, having the same names is way easier ๐Ÿฅน and you can totally change the name (with -E) if you don't like the default ๐Ÿ’–
    • broute is used to make a brouter ๐Ÿงš it has one built-in chain: BROUTING. the targets DROP and ACCEPT have a special meaning in the broute table (these names are kept for compatibility reasons with ebtables-legacy). DROP actually means the frame has to be routed, while ACCEPT means the frame has to be bridged. the BROUTING chain is traversed very early. normally those frames would just be bridged, but you get to decide otherwise right here ๐Ÿ‘‘

๐ŸŽ€ EBTABLES COMMAND LINE ARGUMENTS ๐ŸŽ€

after the initial ebtables -t table command line argument, the remaining arguments can be divided into several groups: commands, miscellaneous commands, rule specifications, match extensions, watcher extensions and target extensions. it's giving organization ๐Ÿ“‹

๐Ÿ‘‘ COMMANDS ๐Ÿ‘‘

the ebtables command arguments specify the actions to perform on the table defined with the -t argument. if you don't use -t to name a table, the commands apply to the default filter table. only one command can be used on the command line at a time, EXCEPT when -L and -Z are combined, or when -N and -P are combined ๐Ÿซถ

  • -A, --append โ€” adds a rule to the very end of the selected chain ๐Ÿ“
  • -D, --delete โ€” deletes the specified rule or rules from the selected chain ๐Ÿ—‘๏ธ there are two ways to do this, bestie. the first is by specifying an interval of rule numbers to delete, right after -D. the syntax is start_nr[:end_nr] (use -L --Ln to list the rules with their rule numbers). when end_nr is left out, every rule starting from start_nr gets deleted. negative numbers are allowed too, and for the details on those, check out the -I command. the second way is by writing out the complete rule exactly as it was when you added it. only the first rule that matches the one you wrote gets deleted, meaning the matching rule with the lowest (positive) rule number ๐ŸŽฏ
  • -C, --change-counters โ€” changes the counters of the specified rule or rules in the selected chain ๐Ÿ”ข same deal as -D, there are two ways. the first is by specifying an interval of rule numbers to change, using the syntax start_nr[:end_nr] (use -L --Ln to see the rule numbers). the details are the same as for -D. the second way is by writing out the complete rule as it was when it was added. only the counters of the first rule that matches get changed, meaning the matching rule with the lowest (positive) rule number ๐Ÿ’… in the first usage, the counters go directly after the interval specification, and in the second usage they go directly after -C. the packet counter comes first, then the byte counter. if the counters you give start with a +, the values get added to the current counter values โž• if they start with a -, the values get subtracted from the current counter values โž– no bounds checking is done, so be careful ๐Ÿ˜ญ and if the counters don't start with + or -, the current counters are simply replaced with the ones you specified โœจ
  • -I, --insert โ€” inserts the specified rule into the selected chain at the specified rule number ๐Ÿงฉ if you don't give a rule number, the rule goes at the head of the chain. if the current number of rules equals N, then the specified number can be anywhere between -N and N+1. for a positive number i, i and i-N-1 point to the same place in the chain where the rule should go. rule number 0 means the place past the last rule in the chain, so using it is the same as using -A ๐Ÿฆ‹ negative rule numbers (strictly smaller than 0) can be really useful when you need to insert more than one rule into a chain ๐ŸŒˆ
  • -P, --policy โ€” sets the policy for the chain to the given target. the policy can be ACCEPT, DROP or RETURN ๐Ÿ”’
  • -F, --flush โ€” flushes the selected chain ๐Ÿšฟ if no chain is selected, then EVERY chain gets flushed. flushing a chain does NOT change the chain's policy, though ๐Ÿ’–
  • -Z, --zero โ€” sets the counters of the selected chain to zero ๐Ÿฅณ if no chain is selected, all the counters get set to zero. the -Z command can be used together with the -L command. when you use both -Z and -L together like this, the rule counters get printed on the screen before they're set to zero, so you can actually see them first ๐Ÿ‘€
  • -L, --list โ€” lists all rules in the selected chain ๐Ÿ“œ if no chain is selected, all chains get listed. the following options change the output of the -L command:
    • --Ln โ€” places the rule number in front of every rule ๐Ÿ”ข this option is incompatible with the --Lx option, so pick one bestie ๐Ÿ™…
    • --Lc โ€” shows the counters at the end of each rule displayed by -L. both a frame counter (pcnt) and a byte counter (bcnt) get displayed. the frame counter shows how many frames matched that specific rule, and the byte counter shows the sum of the frame sizes of those matching frames ๐Ÿ“Š using this option together with --Lx makes the counters get written out in the -c <pcnt> <bcnt> option format ๐ŸŽ€
    • --Lx โ€” changes the output so it produces a set of ebtables commands that construct the contents of the chain, when a chain is specified ๐Ÿ› ๏ธ if no chain is specified, you get ebtables commands to construct the contents of the table, including commands for creating the user-defined chains (if there are any). you can use this set of commands in an ebtables boot or reload script, so the output could be used at system startup ๐Ÿš€ the --Lx option is incompatible with the --Ln listing option. using --Lx together with --Lc will cause the counters to be written out in the -c <pcnt> <bcnt> option format ๐Ÿ’œ
    • --Lmac2 โ€” shows all MAC addresses with the same length, adding leading zeroes where necessary ๐ŸŒท the default representation leaves out leading zeroes in the addresses, so this is the option for when you want everything lined up ๐Ÿ’…

Okay so bestie, we're picking up right where the chain-management commands start getting spicy ๐Ÿ’…โœจ

  • -N, --new-chain โ€” make a brand new user-defined chain with whatever name you give it ๐ŸŽ€ You can have as many of these as you have possible chain names (so, lots ๐ŸŒˆ). The name can be at most 31 characters ๐Ÿ’– A new user-defined chain starts with the standard policy of ACCEPT. Want a different starting policy? Pair -P with -N and the new chain gets that standard target instead. In that combo you don't have to name the chain again for -P ๐Ÿซถ
  • -X, --delete-chain โ€” delete the chain you name ๐Ÿ—‘๏ธ Here's the tea though: if anything still jumps to that chain, ebtables will refuse to delete it ๐Ÿ’€ If you don't name a chain at all, ebtables clears out every user-defined chain that nothing references ๐Ÿงน
  • -E, --rename-chain โ€” rename a chain to something new ๐Ÿฆ‹ You can rename a user-defined chain, but you can also rename a standard chain to whatever suits your taste. Like, if you're a PREFORWARDING girlie over PREROUTING, you can use -E to rename PREROUTING ๐Ÿ™ˆ Important: if you do rename a standard ebtables chain, be sure to mention that when you post on the ebtables mailing lists. It's also wise to use the standard name in your post ๐Ÿ“ฌ Renaming a standard chain like this changes nothing about the structure or functioning of the ebtables kernel table, so it's purely a label thing โœจ
  • --init-table โ€” swap out the current table data and put the initial table data back in its place ๐Ÿ”„

โœจ MISCELLANEOUS COMMANDS โœจ

  • -v, --verbose โ€” verbose mode, bestie ๐Ÿ“ฃ When you're appending, inserting, deleting or replacing, this prints detailed info about the rule (or rules) involved. You can stack -v multiple times to possibly get even more detailed debug statements ๐Ÿ”
  • -V, --version โ€” shows you the version of the ebtables userspace program ๐Ÿท๏ธ
  • -h, --help [list of module names] โ€” gives you a quick rundown of the command syntax ๐Ÿ“– You can also name extensions here and ebtables will try to write help about them, like:
ebtables -h snat log ip arp

Want the full list of extensions the userspace utility supports? Use list_extensions ๐ŸŒธ

  • -j, --jump target โ€” the target of the rule ๐ŸŽฏ It's one of: ACCEPT, DROP, CONTINUE, RETURN, a target extension (see TARGET EXTENSIONS), or a user-defined chain name ๐Ÿ‘‘
  • -M, --modprobe program โ€” when ebtables is talking to the kernel, this program is what it uses to try to automatically load any missing kernel modules ๐Ÿงš
  • --concurrent โ€” this one uses a file lock so that concurrent scripts can update the ebtables kernel tables without stepping on each other ๐Ÿ”’ With ebtables-nft it isn't needed though, so it just gets ignored ๐Ÿคทโ€โ™€๏ธ

โœจ RULE SPECIFICATIONS โœจ

Okay so these command line arguments make up a rule specification, the stuff you use with the add and delete commands ๐Ÿ’œ A ! option placed before a specification inverts that test ๐Ÿ™ƒ There are also some other arguments worth knowing about besides these standard ones, so check out both MATCH EXTENSIONS and WATCHER EXTENSIONS below ๐Ÿ‘€

  • [!] -p, --protocol protocol โ€” the protocol that was responsible for creating the frame ๐ŸŒท This can be a hexadecimal number above 0x0600, a name (like ARP), or LENGTH ๐Ÿ’… The protocol field of an Ethernet frame can also be used to denote the length of the header (802.2/802.3 networks). When that field's value is below or equal to 0x0600, the value equals the size of the header and shouldn't be treated as a protocol number. Instead, every frame where the protocol field is acting as the length field is assumed to be the same "protocol". ebtables calls that protocol LENGTH for these frames ๐Ÿ“ The file /etc/ethertypes can show readable names instead of hex numbers for protocols, so 0x0800 shows up as IPV4 ๐Ÿฆ‹ Using that file isn't case sensitive, and you can check that file for more info. The flag --proto is an alias for this option ๐Ÿ’–
  • [!] -i, --in-interface name โ€” the interface (bridge port) a frame is received on ๐Ÿ“ฅ This one's useful in the INPUT, FORWARD, PREROUTING and BROUTING chains ๐ŸŒˆ If the interface name ends with +, then any interface name that starts with that name (ignoring the +) will match ๐Ÿงฉ The flag --in-if is an alias for this option โœจ
  • [!] --logical-in name โ€” the (logical) bridge interface a frame is received on ๐ŸŒ‰ Also useful in the INPUT, FORWARD, PREROUTING and BROUTING chains ๐Ÿซถ Same + rule applies: end the name with + and anything beginning with that name (ignoring the +) will match ๐Ÿ’ซ
  • [!] -o, --out-interface name โ€” the interface (bridge port) a frame is going to be sent out through ๐Ÿ“ค This is useful in the OUTPUT, FORWARD and POSTROUTING chains ๐Ÿ“ Ending the name with + matches any interface name starting with that name (ignoring the +) ๐ŸŽ€ The flag --out-if is an alias for this option ๐Ÿฆ‹
  • [!] --logical-out name โ€” the (logical) bridge interface a frame is going to be sent out through ๐ŸŒท Useful in the OUTPUT, FORWARD and POSTROUTING chains ๐Ÿ’… Same + deal: end it with + and any name beginning with it (ignoring the +) will match ๐Ÿ”ฅ
  • [!] -s, --source address[/mask] โ€” the source MAC address ๐Ÿง Both the mask and the address get written as 6 hexadecimal numbers separated by colons. You can also use one of these shortcuts for the address: Unicast, Multicast, Broadcast or BGA (Bridge Group Address):
Unicast=00:00:00:00:00:00/01:00:00:00:00:00,
Multicast=01:00:00:00:00:00/01:00:00:00:00:00,
Broadcast=ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff or
BGA=01:80:c2:00:00:00/ff:ff:ff:ff:ff:ff.

Heads up that a broadcast address will also match the multicast specification ๐Ÿ“ฃ The flag --src is an alias for this option ๐Ÿซถ

  • [!] -d, --destination address[/mask] โ€” the destination MAC address ๐ŸŽฏ Check out -s above for more details on MAC addresses, since it works the same way ๐Ÿ’œ The flag --dst is an alias for this option โœจ
  • -c, --set-counter pcnt bcnt โ€” this one is all about counters ๐Ÿ”ข Used with -A or -I, it sets the packet and byte counters of the new rule to pcnt and bcnt respectively ๐ŸŒธ Used with the -C or -D commands instead, only rules whose packet and byte counts equal pcnt and bcnt respectively will match ๐Ÿ™ˆ

โœจ MATCH EXTENSIONS โœจ

Ebtables extensions get dynamically loaded into the userspace tool, so there's no need to explicitly load them with a -m option like you'd do in iptables ๐Ÿงš These extensions handle functionality supported by kernel modules that sit alongside the core ebtables code ๐ŸŒˆ

802_3

Specify 802.3 DSAP/SSAP fields or SNAP type ๐Ÿ’– The protocol must be specified as LENGTH (see the option -p above) ๐Ÿ“

  • [!] --802_3-sap sap โ€” DSAP and SSAP are two one-byte 802.3 fields ๐Ÿ“ The bytes are always equal, so you only need one byte (in hexadecimal) as the argument ๐Ÿ’…
  • [!] --802_3-type type โ€” if the 802.3 DSAP and SSAP values are 0xaa, then the SNAP type field has to be checked to figure out the payload protocol ๐Ÿ” This is a two-byte hexadecimal argument. Only 802.3 frames with DSAP/SSAP 0xaa get checked for type ๐Ÿซถ

among

Matches a MAC address, or a MAC/IP address pair, against a list of MAC addresses and MAC/IP address pairs ๐Ÿฆ‹ A list entry looks like this:

xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip][,]

Multiple list entries are separated by a comma, and giving an IP address that goes with the MAC address is optional ๐Ÿ’œ You can specify multiple MAC/IP address pairs that share the same MAC address with different IP addresses (and vice versa) ๐Ÿ‘ฏโ€โ™€๏ธ If the MAC address doesn't match any entry on the list, the frame does not match the rule (unless ! was used) ๐Ÿ™…โ€โ™€๏ธ

  • [!] --among-dst list โ€” compares the MAC destination against the given list ๐ŸŽฏ If the Ethernet frame has type IPv4 or ARP, then comparison with MAC/IP destination address pairs from the list is possible too โœจ
  • [!] --among-src list โ€” compares the MAC source against the given list ๐ŸŒท If the Ethernet frame has type IPv4 or ARP, then comparison with MAC/IP source address pairs from the list is possible too ๐Ÿ’ซ
  • [!] --among-dst-file file โ€” same as --among-dst, except the list gets read in from the specified file ๐Ÿ“‚
  • [!] --among-src-file file โ€” same as --among-src, except the list gets read in from the specified file ๐Ÿ“

arp

Specify (R)ARP fields ๐ŸŒธ The protocol must be specified as ARP or RARP ๐Ÿซถ

  • [!] --arp-opcode opcode โ€” the (R)ARP opcode, either decimal or a string (for more details, see ebtables -h arp) ๐Ÿ”ข
  • [!] --arp-htype hardware-type โ€” the hardware type ๐Ÿ–ฅ๏ธ This can be a decimal, or the string Ethernet (which sets the type to 1). Most (R)ARP packets have Ethernet as their hardware type ๐Ÿ’–
  • [!] --arp-ptype protocol-type โ€” the protocol type the (r)arp is used for ๐Ÿงฉ It's hexadecimal, or the string IPv4 (denoting 0x0800). Most (R)ARP packets have protocol type IPv4 ๐ŸŒˆ
  • [!] --arp-ip-src address[/mask] โ€” the (R)ARP IP source address specification ๐ŸŽ€
  • [!] --arp-ip-dst address[/mask] โ€” the (R)ARP IP destination address specification ๐ŸŽฏ
  • [!] --arp-mac-src address[/mask] โ€” the (R)ARP MAC source address specification ๐Ÿง
  • [!] --arp-mac-dst address[/mask] โ€” the (R)ARP MAC destination address specification ๐Ÿ“
  • [!] --arp-gratuitous โ€” checks for ARP gratuitous packets ๐Ÿ” This checks whether the IPv4 source address and the IPv4 destination address inside the ARP header are equal ๐Ÿ™ˆ

ip

Specify IPv4 fields ๐ŸŒ The protocol must be specified as IPv4 ๐Ÿ’œ

  • [!] --ip-source address[/mask] โ€” the source IP address ๐Ÿ“ The flag --ip-src is an alias for this option โœจ
  • [!] --ip-destination address[/mask] โ€” the destination IP address ๐ŸŽฏ The flag --ip-dst is an alias for this option ๐Ÿซถ
  • [!] --ip-tos tos โ€” the IP type of service, written in hexadecimal numbers ๐ŸŒท This is for IPv4 ๐Ÿ’…
  • [!] --ip-protocol protocol โ€” the IP protocol ๐Ÿ”ฅ The flag --ip-proto is an alias for this option ๐Ÿ’–
  • [!] --ip-source-port port1[:port2] โ€” okay so this is the source port or port range for the IP protocols 6 (TCP), 17 (UDP), 33 (DCCP) or 132 (SCTP) ๐Ÿซถ. You have to set --ip-protocol to TCP, UDP, DCCP or SCTP first, or it won't work. If you skip port1, you get 0:port2. If you skip port2 but keep the colon, you get port1:65535. --ip-sport is an alias for this one ๐Ÿฆ‹.
  • [!] --ip-destination-port port1[:port2] โ€” same energy, but for the destination port or port range on IP protocols 6 (TCP), 17 (UDP), 33 (DCCP) or 132 (SCTP) ๐ŸŽ€. --ip-protocol still has to be TCP, UDP, DCCP or SCTP. Leave out port1 and you get 0:port2. Leave out port2 but keep the colon and you get port1:65535. --ip-dport is the alias ๐Ÿ’œ.

๐Ÿ’… ip6 ๐Ÿ’…

Specify IPv6 fields. The protocol must be specified as IPv6 ๐ŸŒˆ.

  • [!] --ip6-source address[/mask] โ€” the source IPv6 address. --ip6-src is an alias โœจ.
  • [!] --ip6-destination address[/mask] โ€” the destination IPv6 address. --ip6-dst is the alias for this one ๐ŸŒธ.
  • [!] --ip6-tclass tclass โ€” the IPv6 traffic class, written in hexadecimal numbers ๐Ÿงš.
  • [!] --ip6-protocol protocol โ€” the IP protocol. --ip6-proto is an alias ๐Ÿ’–.
  • [!] --ip6-source-port port1[:port2] โ€” the source port or port range for the IPv6 protocols 6 (TCP), 17 (UDP), 33 (DCCP) or 132 (SCTP) ๐Ÿ‘‘. --ip6-protocol must be TCP, UDP, DCCP or SCTP. Skip port1 and you get 0:port2. Skip port2 with the colon still there and you get port1:65535. --ip6-sport is an alias for this one ๐Ÿ“.
  • [!] --ip6-destination-port port1[:port2] โ€” the destination port or port range for IPv6 protocols 6 (TCP), 17 (UDP), 33 (DCCP) or 132 (SCTP) ๐Ÿ”ฅ. --ip6-protocol has to be TCP, UDP, DCCP or SCTP. Skip port1 and it becomes 0:port2. Skip port2 but keep the colon and it becomes port1:65535. --ip6-dport is the alias ๐Ÿ’œ.
  • [!] --ip6-icmp-type {type[:type]/code[:code]|typename} โ€” match a specific ipv6-icmp type and code. Ranges work for both type and code, and you separate type and code with a slash. Valid numbers for type and code run from 0 to 255 ๐Ÿ™ˆ. If you want one type with every valid code, you can use a symbolic name instead of a number. To see the list of known type names, run:
ebtables --help ip6
This option only works with --ip6-prococol ipv6-icmp, so don't expect it to do anything otherwise ๐Ÿ’€.

๐ŸŒท limit ๐ŸŒท

This module matches at a limited rate using a token bucket filter โœจ. A rule using this extension keeps matching until the limit is reached. You can pair it with the --log watcher to get limited logging, for example. It works the same way as the limit match in iptables ๐Ÿ’–.

  • --limit [value] โ€” the maximum average matching rate. Give it as a number, with an optional /second, /minute, /hour or /day suffix. The default is 3/hour ๐Ÿ•ฐ๏ธ.
  • --limit-burst [number] โ€” the maximum initial number of packets to match. This number gets recharged by one every time the limit above isn't reached, up to this number. The default is 5 ๐ŸŒˆ.

๐Ÿฆ‹ mark_m ๐Ÿฆ‹

  • [!] --mark [value][/mask] โ€” matches frames with the given unsigned mark value ๐Ÿ’œ. If you give both a value and a mask, the logical AND of the frame's mark value and your mask gets taken before it's compared with your mark value. If you only give a mark value, the packet only matches when the frame's mark value equals yours โœจ. If you only give a mask, the logical AND of the frame's mark value and your mask gets taken, and the frame matches when that result is non-zero. Using only a mask is handy when you want to match several mark values at once ๐Ÿซถ.

๐ŸŽ€ pkttype ๐ŸŽ€

  • [!] --pkttype-type type โ€” matches on the Ethernet "class" of the frame, which the generic networking code decides. The possible values are: broadcast (the MAC destination is the broadcast address), multicast (the MAC destination is a multicast address), host (the MAC destination is the receiving network device), or otherhost (none of the above) ๐ŸŒธ.

๐Ÿงš stp ๐Ÿงš

Specify stp BPDU (bridge protocol data unit) fields. The destination address (-d) has to be set to the bridge group address (BGA) ๐ŸŒŠ. For every option where you can give a range of values, it works like this: if you leave out the lower bound but keep the colon, the lowest possible lower bound for that option is used. If you leave out the upper bound but keep the colon, the highest possible upper bound is used ๐Ÿ“.

  • [!] --stp-type type โ€” the BPDU type (0โ€“255). The non-numerical types it recognizes are config, which is a configuration BPDU (=0), and tcn, which is a topology change notification BPDU (=128) ๐ŸŒท.
  • [!] --stp-flags flag โ€” the BPDU flag (0โ€“255). The non-numerical flags it recognizes are topology-change, which is the topology change flag (=1), and topology-change-ack, which is the topology change acknowledgement flag (=128) ๐Ÿ’….
  • [!] --stp-root-prio [prio][:prio] โ€” the root priority (0โ€“65535) range ๐Ÿ‘‘.
  • [!] --stp-root-addr [address][/mask] โ€” the root MAC address. Check the -s option for more details ๐Ÿ”ฅ.
  • [!] --stp-root-cost [cost][:cost] โ€” the root path cost (0โ€“4294967295) range ๐Ÿ’–.
  • [!] --stp-sender-prio [prio][:prio] โ€” the BPDU's sender priority (0โ€“65535) range โœจ.
  • [!] --stp-sender-addr [address][/mask] โ€” the BPDU's sender MAC address. See the -s option for more details ๐Ÿฆ‹.
  • [!] --stp-port [port][:port] โ€” the port identifier (0โ€“65535) range ๐ŸŒˆ.
  • [!] --stp-msg-age [age][:age] โ€” the message age timer (0โ€“65535) range ๐Ÿ•ฐ๏ธ.
  • [!] --stp-max-age [age][:age] โ€” the max age timer (0โ€“65535) range ๐Ÿซง.
  • [!] --stp-hello-time [time][:time] โ€” the hello time timer (0โ€“65535) range ๐Ÿ‘‹.
  • [!] --stp-forward-delay [delay][:delay] โ€” the forward delay timer (0โ€“65535) range ๐Ÿš€.

๐ŸŒธ vlan ๐ŸŒธ

Specify 802.1Q Tag Control Information fields. The protocol must be specified as 802_1Q (0x8100) ๐Ÿ’œ.

  • [!] --vlan-id id โ€” the VLAN identifier field (VID). It's a decimal number from 0 to 4095 ๐ŸŽ€.
  • [!] --vlan-prio prio โ€” the user priority field, a decimal number from 0 to 7. The VID should be set to 0 (the "null VID") or left unspecified. If it's unspecified, the VID is deliberately set to 0 ๐Ÿ™ˆ.
  • [!] --vlan-encap type โ€” the encapsulated Ethernet frame type/length. Give it as a hexadecimal number from 0x0000 to 0xFFFF, or as a symbolic name from /etc/ethertypes ๐Ÿ“.

โœจ WATCHER EXTENSIONS โœจ

Watchers are super chill. They only look at frames passing by. They don't change them, and they don't decide whether to accept the frames ๐Ÿซถ. A watcher only sees the frame if the frame matches the rule, and it sees it before the target gets executed ๐Ÿ‘€.

๐Ÿ“ log ๐Ÿ“

The log watcher writes descriptive data about a frame to the syslog ๐Ÿ’….

  • --log โ€” logs with the default logging options: log-level= info, log-prefix="", no ip logging, no arp logging ๐ŸŒˆ.
  • --log-level level โ€” sets the logging level. For the possible values, check ebtables -h log. The default level is info ๐Ÿ”ฅ.
  • --log-prefix text โ€” sets the prefix text that gets printed at the beginning of the line with the logging information ๐Ÿ’–.
  • --log-ip โ€” logs the ip information when a frame made by the ip protocol matches the rule. By default, there's no ip information logging ๐Ÿฆ‹.
  • --log-ip6 โ€” logs the ipv6 information when a frame made by the ipv6 protocol matches the rule. By default, there's no ipv6 information logging ๐Ÿงš.
  • --log-arp โ€” logs the (r)arp information when a frame made by the (r)arp protocols matches the rule. By default, there's no (r)arp information logging ๐Ÿ™ˆ.

๐Ÿ“ก nflog ๐Ÿ“ก

The nflog watcher passes the packet to the loaded logging backend so it can be logged ๐Ÿ›ฐ๏ธ. This is usually paired with nfnetlink_log as the logging backend, which multicasts the packet through a netlink socket to the specified multicast group. One or more userspace processes can subscribe to that group to receive the packets ๐Ÿซถ.

  • --nflog โ€” logs with the default logging options ๐Ÿ’œ.
  • --nflog-group nlgroup โ€” the netlink group (1โ€“2^32-1) the packets go to. This only applies to nfnetlink_log. The default value is 1 ๐ŸŒธ.
  • --nflog-prefix prefix โ€” a prefix string to include in the log message, up to 30 characters long. It's super useful for telling messages apart in the logs ๐ŸŽ€.
  • --nflog-range size โ€” the number of bytes to copy to userspace. This only applies to nfnetlink_log. nfnetlink_log instances can set their own range, but this option overrides it ๐Ÿ“.
  • --nflog-threshold size โ€” the number of packets to queue inside the kernel before sending them to userspace. This only applies to nfnetlink_log. Higher values mean less overhead per packet, but more delay before the packets reach userspace. The default value is 1 ๐Ÿ•ฐ๏ธ.

๐ŸŒŠ ulog ๐ŸŒŠ

The ulog watcher passes the packet to a userspace logging daemon using netlink multicast sockets ๐Ÿงœ. It's different from the log watcher because the complete packet gets sent to userspace instead of a descriptive text, and netlink multicast sockets are used instead of syslog. This watcher lets userspace programs parse the packets, and the physical bridge in and out ports are included in the netlink messages too ๐Ÿ’….

The ulog watcher module accepts 2 parameters when it's loaded into the kernel (for example with modprobe). nlbufsiz sets how big the buffer for each netlink multicast group is. If you say nlbufsiz=8192, for example, up to eight kB of packets will pile up in the kernel before they get sent to userspace ๐Ÿซง. The buffer can't be bigger than 128kB.

Heads up, bestie: this buffer size gets allocated for each nlgroup you're using, so the total kernel memory usage goes up by that factor ๐Ÿ’€. The default is 4096.

flushtimeout sets how many hundredths of a second go by before the queue gets flushed, even if it isn't full yet. The default is 10, which is one tenth of a second โฐ.

  • --ulog โ€” uses the default settings: ulog-prefix="", ulog-nlgroup=1, ulog-cprange=4096, ulog-qthreshold=1 ๐ŸŒท.
  • --ulog-prefix text โ€” sets the prefix included with the packets sent to userspace ๐ŸŽ€.

๐ŸŽ€ ulog options, continued ๐ŸŽ€

  • --ulog-nlgroup group โ€” okay so this picks which netlink group number to use, anywhere from 1 to 32 ๐Ÿฆ‹ Make sure the netlink group numbers for the iptables ULOG target are different from the ones for the ebtables ulog watcher, bestie, or they'll clash ๐Ÿ’€ The default group is 1.
  • --ulog-cprange range โ€” this sets the maximum copy range sent to userspace for packets that match the rule โœจ The default is 0, which means the max copy range comes from nlbufsiz. Anything bigger than 128*1024 is literally meaningless, because packets sent to userspace are capped at 128*1024 ๐Ÿ™ˆ
  • --ulog-qthreshold threshold โ€” queues at most threshold packets before shipping them to userspace over a netlink socket ๐Ÿ“ฆ Packets can go out before the queue is full too, whenever the ulog kernel timer goes off. How often that timer ticks depends on flushtimeout โฐ

๐Ÿ’… TARGET EXTENSIONS ๐Ÿ’…

๐ŸŒธ arpreply

The arpreply target lives in the PREROUTING chain of the nat table ๐Ÿงš If it sees an ARP request, it automatically replies with an ARP reply, and you can choose the MAC address used for that reply. The protocol has to be ARP. If the ARP message isn't an ARP request, or the request isn't for an IP address on an Ethernet network, it gets ignored (CONTINUE). If the ARP request is malformed, it gets dropped (DROP) ๐Ÿ˜ญ

  • --arpreply-mac address โ€” picks the MAC address to reply with ๐Ÿซถ Both the Ethernet source MAC and the ARP payload source MAC get filled in with this address.
  • --arpreply-target target โ€” the standard target ๐ŸŽฏ After the ARP reply goes out, the rule still needs a standard target so ebtables knows what to do with the ARP request. The default is DROP.

๐Ÿฆ‹ dnat

The dnat target can only be used in the PREROUTING and OUTPUT chains of the nat table ๐Ÿ’œ It changes the destination MAC address, full stop.

  • --to-destination address โ€” changes the destination MAC address to the one you specify โœจ --to-dst is an alias for this, so either one works.
  • --dnat-target target โ€” the standard target โœจ After the dnat, the rule still needs a standard target. The default is ACCEPT. CONTINUE could let you stack multiple target extensions on the same frame ๐ŸŒˆ DROP only really makes sense in the BROUTING chain, but redirect is the more logical pick there. RETURN is allowed too, but not in a base chain (for obvious reasons ๐Ÿ’€).

๐Ÿ“ mark

The mark target can be used in every chain of every table ๐Ÿ‘‘ You can mark a frame or packet in both ebtables and iptables, as long as the bridge-nf code is compiled into the kernel. Both put the marking in the same place, so it's a little channel of communication between ebtables and iptables. Iconic ๐Ÿฅน

  • --mark-set value โ€” marks the frame with the value you give, which has to be non-negative ๐ŸŽ€
  • --mark-or value โ€” ORs the frame with your non-negative value ๐ŸŽ€
  • --mark-and value โ€” ANDs the frame with your non-negative value ๐ŸŽ€
  • --mark-xor value โ€” XORs the frame with your non-negative value ๐ŸŽ€
  • --mark-target target โ€” the standard target ๐ŸŽฏ After marking, the rule still needs a standard target. The default is ACCEPT. CONTINUE lets you do other stuff with the frame in later rules of the chain.

๐Ÿงš redirect

The redirect target swaps the MAC target address for the MAC address of the bridge device the frame arrived on ๐ŸŒŠ It can only be used in the PREROUTING chain of the nat table, and the bridge's MAC becomes the destination address.

  • --redirect-target target โ€” the standard target ๐ŸŽฏ After the MAC redirect, the rule still needs a standard target. The default is ACCEPT. CONTINUE could let you use multiple target extensions on the same frame. DROP in the BROUTING chain lets the frames get routed instead. RETURN is allowed, but not in a base chain.

๐ŸŒท snat

The snat target can only be used in the POSTROUTING chain of the nat table ๐ŸŒธ It changes the source MAC address.

  • --to-source address โ€” changes the source MAC address to the one you pick ๐Ÿ’– --to-src is an alias, so use whichever vibe you like.
  • --snat-target target โ€” the standard target ๐ŸŽฏ After the snat, the rule still needs a standard target. The default is ACCEPT. CONTINUE could let you stack multiple target extensions on the same frame. DROP doesn't make sense here, but you could do it anyway ๐Ÿคทโ€โ™€๏ธ RETURN is allowed, but not in a base chain.
  • --snat-arp โ€” also changes the hardware source address inside the arp header, but only if the packet is an arp message and the hardware address length in that header is 6 bytes ๐Ÿฆ„

๐Ÿ“ FILES ๐Ÿ“

/etc/ethertypes ๐Ÿ—‚๏ธ

๐Ÿ’Œ MAILINGLISTS ๐Ÿ’Œ

See http://netfilter.org/mailinglists.html ๐Ÿ“ฌ

๐Ÿ™ˆ BUGS ๐Ÿ™ˆ

Okay bestie, real talk: the version of ebtables this man page ships with does not support the string match ๐Ÿ˜ญ Also, atomic-options (--atomic-file, --atomic-init, --atomic-save, --atomic-commit) haven't been implemented yet. ebtables-save and ebtables-restore might replace them entirely though, given the inherent atomicity of nftables ๐Ÿซ  And finally, this list is probably not complete. Sorry, babe ๐Ÿ’œ

๐Ÿ”— SEE ALSO ๐Ÿ”—

xtables-nft(8), iptables(8), ip(8) ๐Ÿงš

See https://wiki.nftables.org โœจ


And that's a wrap on ebtables(8)! ๐Ÿ’– This page was written for the December 2011 version, and the manual page is EBTABLES(8) ๐ŸŽ€ Stay iconic, stay bridged, and I love you so much ๐Ÿซถ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from