EBTABLES(8)
๐ 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:filteris 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) andFORWARD(for frames being forwarded by the bridge) ๐ธnatis 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) andPOSTROUTING(for altering frames as they're about to go out) ๐ฆ small note on the naming ofPREROUTINGandPOSTROUTING: technically it'd be more accurate to call themPREFORWARDINGandPOSTFORWARDING, 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 ๐brouteis used to make a brouter ๐ง it has one built-in chain:BROUTING. the targetsDROPandACCEPThave a special meaning in the broute table (these names are kept for compatibility reasons with ebtables-legacy).DROPactually means the frame has to be routed, whileACCEPTmeans the frame has to be bridged. theBROUTINGchain 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 isstart_nr[:end_nr](use-L --Lnto list the rules with their rule numbers). whenend_nris left out, every rule starting fromstart_nrgets deleted. negative numbers are allowed too, and for the details on those, check out the-Icommand. 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 syntaxstart_nr[:end_nr](use-L --Lnto 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-NandN+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 number0means 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 beACCEPT,DROPorRETURN๐-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-Zcommand can be used together with the-Lcommand. when you use both-Zand-Ltogether 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-Lcommand:--Lnโ places the rule number in front of every rule ๐ข this option is incompatible with the--Lxoption, 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--Lxmakes 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--Lxoption is incompatible with the--Lnlisting option. using--Lxtogether with--Lcwill 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-Pwith-Nand 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-Eto 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-vmultiple 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 above0x0600, a name (likeARP), orLENGTH๐ 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 to0x0600, 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 protocolLENGTHfor these frames ๐ The file/etc/ethertypescan show readable names instead of hex numbers for protocols, so0x0800shows up asIPV4๐ฆ Using that file isn't case sensitive, and you can check that file for more info. The flag--protois 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-ifis 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-ifis 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,BroadcastorBGA(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-sabove for more details on MAC addresses, since it works the same way ๐ The flag--dstis an alias for this option โจ -c,--set-counter pcnt bcntโ this one is all about counters ๐ข Used with-Aor-I, it sets the packet and byte counters of the new rule topcntandbcntrespectively ๐ธ Used with the-Cor-Dcommands instead, only rules whose packet and byte counts equalpcntandbcntrespectively 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 are0xaa, 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/SSAP0xaaget 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, seeebtables -h arp) ๐ข - [
!]--arp-htype hardware-typeโ the hardware type ๐ฅ๏ธ This can be a decimal, or the stringEthernet(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 stringIPv4(denoting0x0800). 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-srcis an alias for this option โจ - [
!]--ip-destination address[/mask]โ the destination IP address ๐ฏ The flag--ip-dstis 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-protois 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-protocolto TCP, UDP, DCCP or SCTP first, or it won't work. If you skip port1, you get0:port2. If you skip port2 but keep the colon, you getport1:65535.--ip-sportis 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-protocolstill has to be TCP, UDP, DCCP or SCTP. Leave out port1 and you get0:port2. Leave out port2 but keep the colon and you getport1:65535.--ip-dportis the alias ๐.
๐ ip6 ๐
Specify IPv6 fields. The protocol must be specified as IPv6 ๐.
[!] --ip6-source address[/mask]โ the source IPv6 address.--ip6-srcis an alias โจ.[!] --ip6-destination address[/mask]โ the destination IPv6 address.--ip6-dstis the alias for this one ๐ธ.[!] --ip6-tclass tclassโ the IPv6 traffic class, written in hexadecimal numbers ๐ง.[!] --ip6-protocol protocolโ the IP protocol.--ip6-protois 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-protocolmust be TCP, UDP, DCCP or SCTP. Skip port1 and you get0:port2. Skip port2 with the colon still there and you getport1:65535.--ip6-sportis 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-protocolhas to be TCP, UDP, DCCP or SCTP. Skip port1 and it becomes0:port2. Skip port2 but keep the colon and it becomesport1:65535.--ip6-dportis 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,/houror/daysuffix. The default is3/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), orotherhost(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 areconfig, which is a configuration BPDU (=0), andtcn, which is a topology change notification BPDU (=128) ๐ท.[!] --stp-flags flagโ the BPDU flag (0โ255). The non-numerical flags it recognizes aretopology-change, which is the topology change flag (=1), andtopology-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-soption 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-soption 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 from0x0000to0xFFFF, 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, checkebtables -h log. The default level isinfo๐ฅ.--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 is0, which means the max copy range comes from nlbufsiz. Anything bigger than128*1024is literally meaningless, because packets sent to userspace are capped at128*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-dstis 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-srcis 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
- alpine 3.22: iptables-doc 1.8.11-r1 ยท GPL-2.0-or-later
- alpine 3.23: iptables-doc 1.8.11-r1 ยท GPL-2.0-or-later
- alpine 3.24: iptables-doc 1.8.13-r0 ยท GPL-2.0-or-later
- debian trixie: iptables 1.8.11-2 ยท GPL-2.0-only
- fedora 43: iptables-nft 1.8.11-11.fc43 ยท GPL-2.0-only AND Artistic-2.0 AND ISC
- fedora 43: iptables-nft 1.8.11-12.fc43 ยท GPL-2.0-only AND Artistic-2.0 AND ISC
- fedora 44: iptables-nft 1.8.11-13.fc44 ยท GPL-2.0-only AND Artistic-2.0 AND ISC
- nixpkgs unstable: iptables 1.8.13
- opensuse-leap 16.0: iptables 1.8.11-160000.2.2 ยท Artistic-2.0 AND GPL-2.0-only
- opensuse-leap 16.0: iptables 1.8.11-160000.2.2 ยท Artistic-2.0 AND GPL-2.0-only
- opensuse-leap 16.0: iptables 1.8.11-160000.2.2 ยท Artistic-2.0 AND GPL-2.0-only
- opensuse-leap 16.0: iptables 1.8.11-160000.2.2 ยท Artistic-2.0 AND GPL-2.0-only
- ubuntu questing: iptables 1.8.11-2ubuntu2 ยท GPL-2.0-only
- ubuntu resolute: iptables 1.8.11-2ubuntu3 ยท GPL-2.0-only
- ubuntu stonking: iptables 1.8.11-2ubuntu3 ยท GPL-2.0-only
- ๐ girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms