# iptables and MAC filtering.

## GurliGebis

I want my router (using iptables), to allow a list of MACs (10 computers) to access the internet (forwarding eth1 -> eth0), but only these 10 computers.

So, if somebody else puts his computer on the internal network, he will not be able to use the internet, because the router is only forwarding the trafic on those 10 MAC addresses.

How can I do that?

----------

## jukka

with netfilter. example (don't copy directly...):

```
#!/bin/bash

EXT_IF=eth0

LAN_IF=eth1

iptables -P FORWARD DROP

# edit: bugfix ;-)

#for addr in $(/etc/MAC.allowed); do

for addr in $(</etc/MAC.allowed); do

  iptables -A FORWARD -i $LAN_IF -o $EXT_IF -m mac --mac-source $addr -j ACCEPT

done
```

the file /etc/MAC.allowed used in the example above contains all the mac addresses you want to allow access for, one per line.

hth, jukkaLast edited by jukka on Wed Jan 08, 2003 11:28 am; edited 1 time in total

----------

## rtn

You'll need to make sure you include the MAC filtering into the kernel

as well.

```
CONFIG_IP_NF_MATCH_MAC=y
```

--rtn

----------

## GurliGebis

Thanks, you are great  :Smile: 

Now I'll go and change my /etc/init.d/iptables to run a script instead of loading the saved state  :Smile: 

----------

## GurliGebis

I also want to make sure that only people who has been given an IP by the DHCP is being forwarded, and not people who use a static IP with the same configuration.

How do I do that???

----------

## jukka

 *GurliGebis wrote:*   

> I also want to make sure that only people who has been given an IP by the DHCP is being forwarded, and not people who use a static IP with the same configuration.
> 
> How do I do that???

 

i think you'll have to parse the dhcpd.leases file. but maybe there's a better solution.

----------

## GurliGebis

There has to be, because clients that timeout doesn't get removed from that file.

----------

## delta407

Tell iptables to accept packets only from your DHCP netblock, then.

----------

## GurliGebis

But what if someone sets his computer to have a static IP, that exist inside my DHCP range????

----------

## psp

There is no easy way around this... Perhaps you should look into using authenticated proxy servers or such..?

----------

## GurliGebis

Nahh, going to only allow the MACs, that way it is pretty limited.

----------

## GurliGebis

jukka, your code doesn't work.

Can somebody please make some that does?

----------

## jukka

 *GurliGebis wrote:*   

> jukka, your code doesn't work.
> 
> Can somebody please make some that does?

 

oops. replace this line

```
for addr in $(/etc/MAC.allowed); do
```

with this:

```
for addr in $(</etc/MAC.allowed); do
```

sorry!

----------

## GurliGebis

Got it working now (Used another metode close to yours)

Now, how do I check if the $addr is a valid MAC address (not that it exist on the network, just that it is a valid address)?

----------

## jukka

 *GurliGebis wrote:*   

> Now, how do I check if the $addr is a valid MAC address (not that it exist on the network, just that it is a valid address)?

 

quick bash hack:

```
if [ "${addr//[a-fA-F0-9:]/}" ]; then

  # $addr is a valid mac address (or very close to ;-))

else

  # $addr is not valid

fi
```

in english: remove all characters [a-zA-F0-9:] from the contents of 'addr'. if something remains, addr is definitely invalid.

for 100% correct results you should use a regex, e.g. with sed or grep. example function:

```
checkmac()

{

  echo "$1" | grep '^\([[:xdigit:]]\{2\}:\)\{5\}[[:xdigit:]]\{2\}$' >/dev/null && return 0

  return 1;

}
```

you can call this function and pass a mac address as an argument, as in

```
if checkmac "$addr"; then

  # $addr is a valid mac address

else

  # $addr is not valid

fi
```

hth, jukkaLast edited by jukka on Tue Jan 07, 2003 7:36 pm; edited 2 times in total

----------

## GurliGebis

Ok, now how about the xx:xx:xx:xx:xx:xx:xx:xx notation???

Can't that be done with sed? (If it can, will you write a little function for that too?)

----------

## jukka

 *GurliGebis wrote:*   

> Ok, now how about the xx:xx:xx:xx:xx:xx:xx:xx notation???

 

do you mean xx:xx:xx:xx:xx:xx? exactly that notation does the bash hack ckeck...

 *Quote:*   

> Can't that be done with sed? (If it can, will you write a little function for that too?)

 

already done, see above. you were too fast  :Wink: 

----------

## GurliGebis

hehe, I have to learn to read the whole post  :Smile: 

----------

## GurliGebis

well, I cant get it to work.

Will you please make a whole script, that does work? (Shouldn't take long, since the most is already there)

Here is my script, that return invalid on all addresses (even valid onces):

```

checkmac() 

{ 

  echo "$1" | grep '^\([[:xdigit:]]\{2\}:\)\{5\}[[:xdigit:]]\{2\}$' >/dev/null && return 0 

  return 1; 

}

for addr in `cat /etc/mac.allow`; do

   if checkmac "$addr"; then 

      echo "$addr is valid";

   else 

      echo "$addr is not valid";

   fi

done

```

----------

## jukka

 *GurliGebis wrote:*   

> well, I cant get it to work. [...] return invalid on all addresses (even valid onces)

 

i just tested it and it works. should be correct.

 *Quote:*   

> Will you please make a whole script, that does work? (Shouldn't take long, since the most is already there)

 

wouldn't it be nice if a single word from "your" script was written by you?  :Wink: 

please post the contents of /etc/mac.allow, maybe that helps.

btw: $(</etc/mac.allow) is equivalent to `cat /etc/mac.allow`, but faster.

----------

## GurliGebis

It works now, I made a misspelling in it  :Smile:  (Not easy when you are tired)

So it is working now  :Smile: 

Again, thanks for your help.

----------

