Home arrow Latest Tutorials arrow Setup a PPPoE Server with MPD II
Setup a PPPoE Server with MPD II PDF
Saturday, 26 April 2008
For a small number of users an Internet line with public IP is needed, a FreeBSD machine will be setup as Router with NAT (Network Address Translation) and also as PPPoE server. This router will have two network cards, one with public IP, the other does not need to have IP (still you can setup an IP, if you want to access that box from LAN, on a private subnet). The PPPoE server will answer at requests from PPPoE clients on LAN and will create a Point to Point tunnel between server and client.

 

PPPoE Server FreeBSD, Linux, Unix

 

 For this simple example we only need one Internet line, setup on WAN interface of router, a FreeBSD router on which we will enable routing (adding gateway_enable="YES" in rc.conf), we will setup NAT with natd and use IPFW as a firewall, and and we will install mpd and configure it to run as PPPoE Server.

 Clients from LAN will create a PPPoE connection (on Windows XP or will use raspppoe client, if they have an older version of Windows that does not support PPPoE), and using their username and password will be able to authenticate on PPPoE server.

 To use this setup you do not need Radius, mpd is able to authenticate users using a plain text file (mpd.secret). If you will have a lot of LAN users is better to use Radius, which is an authentication server because it has a lot of features, and also if you want the sollution to be scalable you will need Radius, so all your PPPoE Servers will use the same Radius authentication server.

To find out how you can setup multiple PPPOE servers for load balancing with radius used for authentication, please see our tutorial  Setup Load Balanced PPPoE Servers with OSPF .

In the following is presented a configuration example of the router / PPPoE server for this simple setup. This could be only a test for you, before building a Load Ballanced PPPoE server solution. Use this setup only for learning, do not use it in production.

Asuming that our config informations are:
Public IP: 80.10.10.2 (gateway 80.10.0.1, netmask 255.255.255.0)
Private IP: 10.0.0.1 (netmask 255.255.255.0), here we can choose any private IP
Hostname: pppoe (we choose any hostname we want)
WAN Interface: fxp0
LAN Interface: fxp1

Following it is a configuration file for your kernel. Append this to your GENERIC configuration file of your kernel.

# ------ kernel configuration file ------------
# netgraph options
options HZ=1000
options NETGRAPH
options NETGRAPH_PPPOE
options NETGRAPH_SOCKET

options NETGRAPH_CISCO
options NETGRAPH_ECHO
options NETGRAPH_FRAME_RELAY
options NETGRAPH_HOLE
options NETGRAPH_KSOCKET
options NETGRAPH_LMI
options NETGRAPH_RFC1490
options NETGRAPH_TTY

options NETGRAPH_ASYNC
options NETGRAPH_BPF
options NETGRAPH_ETHER
options NETGRAPH_IFACE
options NETGRAPH_KSOCKET
options NETGRAPH_L2TP
options NETGRAPH_MPPC_ENCRYPTION
options NETGRAPH_PPP
options NETGRAPH_PPTPGRE
options NETGRAPH_TEE
options NETGRAPH_UI
options NETGRAPH_VJC

# support for ALTQ Traffic Shaping
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_PRIQ

# support for PF Firewall
device mem
device pf
device pflog
device pfsync
# ----------end kernel config file ------------


After editing configuration file of the kernel, recompile and install the kernel:
make -j2 buildkernel KERNCONF=PPPOE
make installkernel KERNCONF=PPPOE
(asuming your kernel config file is located in /usr/src/sys/i386/conf/ and is named PPPOE)

 

We will present how you can configure your PPPOE server using both IPFW and PF. For the first case, when using IPFW:

The config files will be:

 # ----------- rc.conf file ----------------------
defaultrouter="80.10.10.1"
gateway_enable="YES"
hostname="pppoe.example.com"
ifconfig_fxp0="inet 80.10.10.2  netmask 255.255.255.0"
ifconfig_fxp1="inet 10.0.0.1  netmask 255.255.255.0"
sshd_enable="YES"
usbd_enable="YES"
firewall_enable="YES"
firewall_script="/etc/rc.firewall"
natd_enable="YES"
natd_interface="fxp0"
natd_flags="" 

# -----------------end rc.conf------------------

# ----------------- rc.firewall file --------------

fwcmd=/sbin/ipfw                                        #specify the ipfw command
$fwcmd add 00010 divert 8668 ip from any to any via fxp0
$fwcmd add 00020 allow ip from any to any via lo0       #permit anything local

$fwcmd add 00050 deny tcp from any to any dst-port 135-139
$fwcmd add 00051 deny udp from any to any dst-port 135-139
$fwcmd add 00052 deny tcp from any to any dst-port 445
$fwcmd add 00052 deny udp from any to any dst-port 445

#$fwcmd add 00030 deny ip from any to 127.0.0.0/8       #deny localhost to any access
#$fwcmd add 00040 deny ip from 127.0.0.0/8 to any       #deny any access to localhost
#$fwcmd add 00070 allow ip from 10.0.0.0/16 to 10.0.0.0/16

# clients rules will be entered here dinamically 


$fwcmd add 65000 allow ip from me to any                #let the gate go anywhere *SECURITY
$fwcmd add 65100 allow ip from any to me                #let the gate get anything *SECURITY

# --------------- end rc.firewall file ------------ 

# -------------- mpd.conf file -----------------

default:
 log auth iface

 load s0
 load s1
 load s2
 load s3

s0:
 new -i ng0 s0 ppplink0
 load generic

s1:
 new -i ng1 s1 ppplink1
 load generic

s2:
 new -i ng2 s2 ppplink2
 load generic

s3:
 new -i ng3 s3 ppplink3
 load generic
 

generic:
    set iface enable proxy-arp
    set pppoe iface fxp1
    set iface idle 0
    set iface mtu 1462
    set iface enable tcpmssfix
    set link accmap 0
    set link enable pap
    set link enable chap
    set link accept chap-msv2
    set link max-redial -1
    set link keep-alive 10 80
    set link no acfcomp
    set link no protocomp
    set ipcp no vjcomp
    set ipcp dns 80.20.0.1 80.20.0.2
    set bundle enable noretry
    set bundle enable multilink
    set auth max-logins 1
    set pptp disable windowing
    set pptp enable always-ack
    set iface up-script /usr/local/etc/mpd4/addclient.sh
    set iface down-script /usr/local/etc/mpd4/removeclient.sh

# ---------------- end mpd.conf file ----------

# --------------- mpd.links file ----------------

ppplink0:
 set link type pppoe
 set pppoe iface fxp1
 set pppoe service "*"
 set pppoe enable incoming

ppplink1:
 set link type pppoe
 set pppoe iface fxp1
 set pppoe service "*"
 set pppoe enable incoming

ppplink2:
 set link type pppoe
 set pppoe iface fxp1
 set pppoe service "*"
 set pppoe enable incoming

ppplink3:
 set link type pppoe
 set pppoe iface fxp1
 set pppoe service "*"
 set pppoe enable incoming

# --------------end mpd.links file -------------


# -------------- mpd.secret file ---------------
# here you have for each user the password and the ip he receives when connecting
cust1 "passwordcust1" 10.0.0.10
cust2 "passwordcust2" 10.0.0.11

# -------------- end mpd.secret file ----------

 # -------------- bandwidth.conf file ---------------
# here you have bandwidth information for every client
# customer downkb upkb
cust1 512 256
cust2 1024 512

# -------------- end bandwidth.conf file ----------

addclient.sh and removeclient.sh are the scripts that run when each client connects / disconnects and add / remove from firewall the rules that allow the user to pass through firewall and the proper pipes to limit his bandwidth to the values from bandwidth.conf 

 # -------------- addclient.sh file ---------------

#!/bin/sh
user=$5                 #grab args off the command line (USER, type, HISADDR, INTERFACE)
type=$2
clientip=$4
int=$1
fwcmd=/sbin/ipfw        #specify firewall command

usernum1=${int#ng}
usernum=`expr $usernum1 + 1`
inkbps=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f2`            #grab max inbound throughput
outkbps=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f3`   #grab max outbound throughput

if [ -z $usernum ]; then                                                #if no usernum
currentusers=`wc -l /usr/local/etc/mpd/bandwidth.conf | cut -d " " -f8` #count the lines in the file
usernum=`expr $currentusers + 1`                                #add one to the count of lines
echo newusernum: $usernum
fi

if [ -z $outkbps ]; then                                                #if no inkbps, default to 1024kbps
        outkbps=1024
        echo newoutkbps: $outkbps
fi


if [ -z $inkbps ]; then                                                 #if no outkbps, default to 1024kbps
        inkbps=1024
        echo newinkbps: $inkbps
fi

pipein=`echo $usernum*2 | bc`                                           #the firewall pipe and rule numbers
pipeout=`expr $pipein + 1`                                              #get seeded by the usernumber
fwrulein=`expr $pipein + 1000`
fwruleout=`expr $fwrulein + 1`
fwholein=`expr $pipein + 33000`
fwholeout=`expr $fwholein + 1`


$fwcmd pipe $pipein config bw ${inkbps}Kbit/s                           #make an inbound pipe of the right size
$fwcmd pipe $pipeout config bw ${outkbps}Kbit/s                         #same for outgoing

$fwcmd add $fwrulein pipe $pipein ip from any to $clientip in           #force traffic through the correct pipe
$fwcmd add $fwruleout pipe $pipeout ip from $clientip to any via $int  
#$fwcmd add $fwruleout pipe $pipeout ip from $clientip to any out      
$fwcmd add $fwholein permit ip from any to $clientip                    #allow that traffic through firewall
$fwcmd add $fwholeout permit ip from $clientip to any                  
echo `date`,$usernum,$user,$type,$clientip,$int,$inkbps,$outkbps >> /var/log/mpd.output

# -------------- end addclient.sh file ----------

# ---------------- removeclient.sh file ------------

 #!/bin/sh
user=$3
type=$2
int=$1
clientip=`/sbin/ifconfig $int | grep -w inet | cut -d" " -f4`
fwcmd=/sbin/ipfw

usernum1=${int#ng}
usernum=`expr $usernum1 + 1`
inkbps=`grep ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f2`
outkbps=`grep ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f3`

if [ -z $usernum ]; then
        currentusers=`wc -l /usr/local/etc/mpd/bandwidth.conf | cut -d " " -f8`
        usernum=`expr $currentusers + 1`
        echo newusernum: $usernum
fi

if [ -z $outkbps ]; then
        outkbps=1024
        echo newoutkbps: $outkbps
fi

if [ -z $inkbps ]; then
        inkbps=1024
        echo newinkbps: $inkbps
fi

pipein=`echo $usernum*2 | bc`
pipeout=`expr $pipein + 1`
fwrulein=`expr $pipein + 1000`
fwruleout=`expr $fwrulein + 1`
fwholein=`expr $pipein + 33000`
fwholeout=`expr $fwholein + 1`


$fwcmd pipe delete $pipein
$fwcmd pipe delete $pipeout
$fwcmd delete $fwrulein pipe $pipein
$fwcmd delete $fwruleout pipe $pipeout
$fwcmd delete $fwholein
$fwcmd delete $fwholeout

echo 'disconnecting '`date`,$user,$type,$int,$inkbps,$outkbps >> /var/log/mpd.output

 # ---------------- end removeclient.sh file ---------- 

Configurations using PF + HFSC

 # ----------- rc.conf file ----------------------
defaultrouter="80.10.10.1"
gateway_enable="YES"
hostname="pppoe.example.com"
ifconfig_fxp0="inet 80.10.10.2  netmask 255.255.255.0"
ifconfig_fxp1="inet 10.0.0.1  netmask 255.255.255.0"
sshd_enable="YES"
usbd_enable="YES"
pf_enable="YES"
pf_rules="/etc/pf.conf"

# -----------------end rc.conf------------------

# ------------- pf.conf file --------------------

ext_if        = "fxp0"
int_if        = "fxp1"
local_net     = "10.0.0.0/16"
ssh_ports     = "{ 22 2022 }"
priv_nets= " { 127.0.0.0/8, 192.168.0.0, 172.16.0.0/12, 10.0.0.0/8 }"

set optimization normal
set timeout tcp.closed 1
set timeout { interval 10, frag 30 }
set timeout { tcp.first 120, tcp.opening 30, tcp.established 86400 }
set timeout { tcp.closing 900, tcp.finwait 45, tcp.closed 90 }
set timeout { udp.first 60, udp.single 30, udp.multiple 60 }
set timeout { icmp.first 20, icmp.error 10 }
set timeout { other.first 60, other.single 30, other.multiple 60 }
set timeout { adaptive.start 0, adaptive.end 0 }
set limit   { states 20000, frags 20000 }

scrub in all
scrub out all random-id max-mss 1440

altq on fxp0 hfsc bandwidth 10800Kb queue { def_out , tcp_ack, ssh_out, dns_out }#queues_out
altq on em0 hfsc bandwidth 110Mb queue {lan_in , down }#queues_g

queue def_out priority 6 bandwidth 256Kb hfsc(realtime 256Kb linkshare 10% upperlimit 1024Kb default)
queue ssh_out priority 7 bandwidth 16Kb hfsc(realtime 32Kb upperlimit 64Kb)
queue tcp_ack priority 7 bandwidth 256Kb hfsc(realtime 256Kb upperlimit 256Kb)
queue dns_out priority 6 bandwidth 16Kb hfsc(realtime 32Kb upperlimit 64Kb)

queue lan_in bandwidth 70Mb hfsc(realtime 70Mb linkshare 10% upperlimit 70Mb default)
queue down bandwidth 10800Kb hfsc (realtime 10800Kb upperlimit 10800Kb)

nat on $ext_if from { 10.0.0.1/24 } to any -> ($ext_if) 

#pass for loopback interface
pass quick on lo0 label "loopback"

#blocare ip-uri din retele private
block in quick on fxp0 from $priv_nets to any label "bloc-private"
block out quick on fxp0 from any to $priv_nets label "bloc-private"

#blocare porturi virusi
block quick proto { tcp udp } from any to any port 445
block quick proto { tcp udp } from any to any port 135:139

antispoof for $ext_if
antispoof for $int_if

pass in proto gre to any
pass out proto gre to any

pass out quick on $ext_if inet proto tcp from $ext_if to any port $ssh_ports queue ssh_out label "ssh-out"
pass in quick on $ext_if inet proto tcp from any to $ext_if port $ssh_ports queue ssh_out label "ssh-out"

#dns requests
pass in quick on $ext_if inet proto { tcp udp } from any to any port domain queue dns_out label "dns_out"
pass out quick on $ext_if inet proto { tcp udp } from $ext_if to any port domain queue dns_out label "dns_out"

#allow local traffic
pass out quick on $int_if from $int_if to $local_net queue lan_in label "localnet out"
pass in quick on $int_if from $local_net to $int_if queue lan_in label "localnet in"

# here are pppoe users rules
anchor users
load anchor users from "/usr/local/etc/mpd/pf_rules"

#pass for ext_if
pass out quick on $ext_if from $ext_if to any
pass in quick on $ext_if from any to $ext_if

block in quick on $ext_if all label "block-fxp0-in"
block out quick on $ext_if all label "block-fxp0-out"

block in quick on $int_if all label "block-int_if-in"
block out quick on $int_if all label "block-int_if-out"

# ----------------end pf.conf------------------

The rules for connected clients will be added at connection time in the file /usr/local/etc/mpd/pf_rules and removed when they disconnect.
Here is an example of a set of rules added after a client connects:

pass quick on ng102 from $lan_ip to any
pass quick on ng102 from any to $lan_ip
pass in quick on ng102 from 10.0.0.45 to any queue ( queue_unique_name_o , tcp_ack ) label queue_unique_name_o
pass out quick on ng102 from any to 10.0.0.45 queue queue_unique_name_i label queue_unique_name_i
pass out quick on $ext_if inet from 10.0.0.45 to any  #ng102
pass in quick on $ext_if inet from any to 10.0.0.45   #ng102

# ------------------------ addclient.sh --------------------------- 

 #!/bin/sh
user=$5                 #grab args off the command line (USER, type, HISADDR, INTERFACE, MAC)
type=$2
clientip=$4
int=$1
mac=$6

int_if="fxp1"
ext_if="fxp0"
lan_ip="10.0.0.1"
usernum1=${int#ng}
usernum=`expr $usernum1 + 1`

in_max=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f2`            #grab max inbound throughput
out_max=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f3`           #grab max inbound throughput
in_g=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f4`      #grab max outbound throughput

queue=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f1 | cut -c 1-13`

echo "pass quick on "$int" from "$lan_ip" to any" >> /usr/local/etc/mpd/pf_rules
echo "pass quick on "$int" from any to "$lan_ip""  >>  /usr/local/etc/mpd/pf_rules

echo "pass in quick on "$int" from "$clientip" to any queue ( "$queue"_o , tcp_ack ) label "$queue"_o" >> /usr/local/etc/mpd/pf_rules
echo "pass out quick on "$int" from any to "$clientip" queue "$queue"_i label "$queue"_i"  >>  /usr/local/etc/mpd/pf_rules

echo "pass out quick on "$ext_if" inet from "$clientip" to any  #"$int"" >> /usr/local/etc/mpd/pf_rules
echo "pass in quick on "$ext_if" inet from any to "$clientip"   #"$int""  >>  /usr/local/etc/mpd/pf_rules

/sbin/pfctl -a users -f /usr/local/etc/mpd/pf_rules

echo `date`,$usernum,$user,$clientip,$int,$in_max,$out_max,$in_g,$mac >> /var/log/mpd.output

# ------------------------ end addclient.sh ---------------------------

# ------------------------ removeclient.sh --------------------------

#!/bin/sh
user=$3
type=$2
int=$1
clientip=`/sbin/ifconfig $int | grep -w inet | cut -d" " -f4`

in_max=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f2`            #grab max inbound throughput
out_max=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f3`           #grab max inbound throughput
in_g=`grep -w ""$user"" /usr/local/etc/mpd/bandwidth.conf | cut -d" " -f4`      #grab max outbound throughput

rules=`/bin/cat /usr/local/etc/mpd/pf_rules | grep -w `$int
/bin/cat /usr/local/etc/mpd/pf_rules | grep -v -w $rules > /usr/local/etc/mpd/pf_temp
cp /usr/local/etc/mpd/pf_temp /usr/local/etc/mpd/pf_rules
rm /usr/local/etc/mpd/pf_temp

#reload new rules
/sbin/pfctl -a users -f /usr/local/etc/mpd/pf_rules

echo 'disconnecting '`date`,$user,$int,$clientip,$in_max,$out_max,$in_g >> /var/log/mpd.output

# ------------------------ end removeclient.sh --------------------------

 

 

Last Updated ( Saturday, 26 April 2008 )
 
< Prev   Next >

Other BSD Systems

OpenBSD

Misc

Solaris

Polls

Best BSD firewall?