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.
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 --------------------------
|