Difference between revisions of "PPP Loadbalance Debian"

From MS Computech
Jump to: navigation, search
Line 2: Line 2:
  
 
[http://neutron.debianclub.com/neutron/projects/ppp-balance/ppp-balance.sh Source]  
 
[http://neutron.debianclub.com/neutron/projects/ppp-balance/ppp-balance.sh Source]  
<pre class="brush:bash">#!/bin/bash
+
<pre class="brush:bash">
 +
#!/bin/bash
  
 
#############################################################
 
#############################################################
Line 9: Line 10:
 
# Author: Neutron Soutmun                                  #
 
# Author: Neutron Soutmun                                  #
 
# Created: 2008-04-28                                      #
 
# Created: 2008-04-28                                      #
# Copyright: © 2008 Neutron Soutmun [email protected]   #
+
# Copyright: © 2008 Neutron Soutmun <[email protected]> #
 
# License: GPL-2                                            #
 
# License: GPL-2                                            #
 
#############################################################
 
#############################################################
Line 16: Line 17:
  
 
##
 
##
# LOG_DIR&nbsp;: Store the neccessary log files for ppp load balance processing.
+
# LOG_DIR : Store the neccessary log files for ppp load balance processing.
 
##
 
##
 
LOG_DIR=/var/log/ppp-balance
 
LOG_DIR=/var/log/ppp-balance
  
 
##  
 
##  
# TABLE_PREFIX&nbsp;: The prefix for the table name that specified in
+
# TABLE_PREFIX : The prefix for the table name that specified in
 
#                /etc/iproute2/rt_tables for identification of route.
 
#                /etc/iproute2/rt_tables for identification of route.
 
##
 
##
Line 27: Line 28:
  
 
##
 
##
# GAMEONLINE_ROUTE_TO_IFNO&nbsp;: The interface number which desired to be the  
+
# GAMEONLINE_ROUTE_TO_IFNO : The interface number which desired to be the  
 
#                            GameOnline routing path.
 
#                            GameOnline routing path.
 
#                            You must set the netfilter rules for this function
 
#                            You must set the netfilter rules for this function
Line 44: Line 45:
  
 
##
 
##
# RELOAD_SQUID&nbsp;: Force to reload the squid config, workaround for the system
+
# RELOAD_SQUID : Force to reload the squid config, workaround for the system
 
#                that running squid process, disable set it to 0
 
#                that running squid process, disable set it to 0
 
##
 
##
Line 50: Line 51:
  
 
##
 
##
# VERBOSE&nbsp;: Verbose mode, display all logs and errors
+
# VERBOSE : Verbose mode, display all logs and errors
 
#          disable set it to 0.
 
#          disable set it to 0.
 
##
 
##
Line 78: Line 79:
 
     echo "${timestamp}: $1"  
 
     echo "${timestamp}: $1"  
 
   fi
 
   fi
   echo "${timestamp}: $1" &gt;&gt; ${LOG_FILE}
+
   echo "${timestamp}: $1" >> ${LOG_FILE}
 
}
 
}
  
Line 86: Line 87:
 
     echo "${timestamp}: ERROR! - $1"
 
     echo "${timestamp}: ERROR! - $1"
 
   fi
 
   fi
   echo "${timestamp}: ERROR! - $1" &gt;&gt; ${LOG_FILE}
+
   echo "${timestamp}: ERROR! - $1" >> ${LOG_FILE}
 
   exit $2
 
   exit $2
 
}
 
}
Line 93: Line 94:
  
 
# Check log dir
 
# Check log dir
if [&nbsp;! -d ${LOG_DIR} ]; then
+
if [ ! -d ${LOG_DIR} ]; then
 
   mkdir -p ${LOG_DIR} || exit 1
 
   mkdir -p ${LOG_DIR} || exit 1
 
fi
 
fi
  
 
# Check neccessary program
 
# Check neccessary program
if [&nbsp;! -f ${IP} ]; then
+
if [ ! -f ${IP} ]; then
   error "The 'iproute2' package is not installed properly&nbsp;?!!" 1
+
   error "The 'iproute2' package is not installed properly ?!!" 1
 
fi
 
fi
  
Line 106: Line 107:
 
if [ $rt_tables -eq 0 ]; then
 
if [ $rt_tables -eq 0 ]; then
 
   ## Create the route tables name from prefix
 
   ## Create the route tables name from prefix
   echo ""  &gt;&gt; ${RT_TABLES}
+
   echo ""  >> ${RT_TABLES}
   echo "#" &gt;&gt; ${RT_TABLES}
+
   echo "#" >> ${RT_TABLES}
   echo "# Added by PPP Load Balancer" &gt;&gt; ${RT_TABLES}
+
   echo "# Added by PPP Load Balancer" >> ${RT_TABLES}
   echo "#" &gt;&gt; ${RT_TABLES}
+
   echo "#" >> ${RT_TABLES}
  
   for (( i = 0; i &lt; 10; i++ )); do
+
   for (( i = 0; i < 10; i++ )); do
     echo "20${i} ${TABLE_PREFIX}${i}" &gt;&gt; ${RT_TABLES}
+
     echo "20${i} ${TABLE_PREFIX}${i}" >> ${RT_TABLES}
 
   done
 
   done
 
fi
 
fi
Line 118: Line 119:
  
 
# Clear the temporary files
 
# Clear the temporary files
echo "" &gt; ${TEMP_FILE}
+
echo "" > ${TEMP_FILE}
  
 
del_old_rule () {
 
del_old_rule () {
 
   log "Removing old rules ..."
 
   log "Removing old rules ..."
   ${IP} rule show | grep ${TABLE_PREFIX} | grep -v "all to" &gt; ${OLD_RULE_FILE}
+
   ${IP} rule show | grep ${TABLE_PREFIX} | grep -v "all to" > ${OLD_RULE_FILE}
  
 
   while read line
 
   while read line
Line 139: Line 140:
 
     fi
 
     fi
  
   done &lt; ${OLD_RULE_FILE}  
+
   done < ${OLD_RULE_FILE}  
 
}
 
}
  
 
update_route () {
 
update_route () {
 
   log "Updating new route ..."
 
   log "Updating new route ..."
   echo "" &gt; ${NEXTHOP_FILE}
+
   echo "" > ${NEXTHOP_FILE}
  
 
   for PPP in ${PPP_LIST}
 
   for PPP in ${PPP_LIST}
Line 162: Line 163:
  
 
     log "nexthop via ${new_ip} dev ${PPP} weight 1"
 
     log "nexthop via ${new_ip} dev ${PPP} weight 1"
     echo "nexthop via ${new_ip} dev ${PPP} weight 1 " &gt;&gt; ${NEXTHOP_FILE} 2&gt;&amp;1
+
     echo "nexthop via ${new_ip} dev ${PPP} weight 1 " >> ${NEXTHOP_FILE} 2>&1
 
   done
 
   done
 
}
 
}
Line 203: Line 204:
 
     changes=1  
 
     changes=1  
 
   fi
 
   fi
   echo ${PPP}:${if_ip}:${TABLE_PREFIX}${table_id} &gt;&gt; ${TEMP_FILE}
+
   echo ${PPP}:${if_ip}:${TABLE_PREFIX}${table_id} >> ${TEMP_FILE}
 
done
 
done
  
Line 212: Line 213:
 
fi
 
fi
  
if [ ${OLD_IF_COUNT}&nbsp;!= ${IF_COUNT} ]; then
+
if [ ${OLD_IF_COUNT} != ${IF_COUNT} ]; then
 
   log "Links size changed!"
 
   log "Links size changed!"
 
   changes=1
 
   changes=1
Line 228: Line 229:
 
     ${SQUID} reload
 
     ${SQUID} reload
 
   fi
 
   fi
   date &gt;&gt; ${REDIAL_LOG_FILE}
+
   date >> ${REDIAL_LOG_FILE}
  
 
   success=`${IP} route | grep nexthop | wc -l`
 
   success=`${IP} route | grep nexthop | wc -l`
 
   if [ ${success} -gt 0 ]; then
 
   if [ ${success} -gt 0 ]; then
 
     cp ${TEMP_FILE} ${OLD_IF_FILE}
 
     cp ${TEMP_FILE} ${OLD_IF_FILE}
     echo ${IF_COUNT} &gt; ${OLD_IF_COUNT_FILE}
+
     echo ${IF_COUNT} > ${OLD_IF_COUNT_FILE}
 
     log "Updated!"
 
     log "Updated!"
 
   else
 
   else
Line 244: Line 245:
 
### END ###
 
### END ###
 
</pre>
 
</pre>
Make Cron  
+
Cron Job
 
<pre>nano /etc/cron.d/ppp-balance
 
<pre>nano /etc/cron.d/ppp-balance
</pre><pre>*/1 *    * * *    root  /usr/local/bin/ppp-balance.sh &gt;/dev/null 2&gt;&amp;1
+
</pre><pre>*/1 *    * * *    root  /usr/local/bin/ppp-balance.sh >/dev/null 2>&1
 
</pre><pre>/etc/init.d/cron restart
 
</pre><pre>/etc/init.d/cron restart
 
</pre>
 
</pre>

Revision as of 12:37, 28 June 2009

PPP Loadbalance Debian Script

Source

#!/bin/bash

#############################################################
# PPP Load Balancer Script                                  #
#                                                           #
# Author: Neutron Soutmun                                   #
# Created: 2008-04-28                                       #
# Copyright: © 2008 Neutron Soutmun <[email protected]> #
# License: GPL-2                                            #
#############################################################

VERSION=0.1.1

##
# LOG_DIR : Store the neccessary log files for ppp load balance processing.
##
LOG_DIR=/var/log/ppp-balance

## 
# TABLE_PREFIX : The prefix for the table name that specified in
#                /etc/iproute2/rt_tables for identification of route.
##
TABLE_PREFIX=isp

##
# GAMEONLINE_ROUTE_TO_IFNO : The interface number which desired to be the 
#                            GameOnline routing path.
#                            You must set the netfilter rules for this function
#                            will work properly.
#                            To disable this, set it to -1
#
# Example netfilter rules:
#
# # iptables -t mangle -A PREROUTING -i eth0 -p tcp \
#     -m multiport --dports 1025:65535 -j MARK --set-mark 0x4
# # iptables -t mangle -A PREROUTING -i eth0 -p udp \
#     -m multiport --dports 1025:65535 -j MARK --set-mark 0x4
#
##
GAMEONLINE_ROUTE_TO_IFNO=3

##
# RELOAD_SQUID : Force to reload the squid config, workaround for the system
#                that running squid process, disable set it to 0
##
RELOAD_SQUID=1

##
# VERBOSE : Verbose mode, display all logs and errors
#           disable set it to 0.
##
VERBOSE=1

###################################
### Do not need to change below ###
###################################

IP=/sbin/ip
IFCONFIG=/sbin/ifconfig
SQUID=/etc/init.d/squid

RT_TABLES=/etc/iproute2/rt_tables

OLD_IF_FILE=${LOG_DIR}/old-if.log
OLD_IF_COUNT_FILE=${LOG_DIR}/old-if-cnt.log
OLD_RULE_FILE=${LOG_DIR}/old-rule.log
NEXTHOP_FILE=${LOG_DIR}/nexthop.log
REDIAL_LOG_FILE=${LOG_DIR}/redial.log
TEMP_FILE=${LOG_DIR}/temp.log
LOG_FILE=${LOG_DIR}/ppp-balance.log

log() {
  timestamp=`date`
  if [ ${VERBOSE} -gt 0 ]; then
    echo "${timestamp}: $1" 
  fi
  echo "${timestamp}: $1" >> ${LOG_FILE}
}

error() {
  timestamp=`date`
  if [ ${VERBOSE} -gt 0 ]; then
    echo "${timestamp}: ERROR! - $1"
  fi
  echo "${timestamp}: ERROR! - $1" >> ${LOG_FILE}
  exit $2
}

### Check if the system ready ###

# Check log dir
if [ ! -d ${LOG_DIR} ]; then
  mkdir -p ${LOG_DIR} || exit 1
fi

# Check neccessary program
if [ ! -f ${IP} ]; then
  error "The 'iproute2' package is not installed properly ?!!" 1
fi

# Check pre-defined tables name
rt_tables=`cat ${RT_TABLES} | grep "200	${TABLE_PREFIX}0" | wc -l`
if [ $rt_tables -eq 0 ]; then
  ## Create the route tables name from prefix
  echo ""  >> ${RT_TABLES}
  echo "#" >> ${RT_TABLES}
  echo "# Added by PPP Load Balancer" >> ${RT_TABLES}
  echo "#" >> ${RT_TABLES}

  for (( i = 0; i < 10; i++ )); do
    echo "20${i}	${TABLE_PREFIX}${i}" >> ${RT_TABLES}
  done
fi


# Clear the temporary files
echo "" > ${TEMP_FILE}

del_old_rule () {
  log "Removing old rules ..."
  ${IP} rule show | grep ${TABLE_PREFIX} | grep -v "all to" > ${OLD_RULE_FILE}

  while read line
  do
    #echo $line
    line_ip=`echo $line | cut -d' ' -f3`
    line_table=`echo $line | cut -d' ' -f5`
    
    check=`echo ${line_table} | grep ${TABLE_PREFIX}`
    if [ $? -eq 0 ]; then
      log "${IP} rule del from ${line_ip} table ${line_table}"
      ${IP} rule del from ${line_ip} table ${line_table}

      log "${IP} route flush table ${line_table}"
      ${IP} route flush table ${line_table}
    fi

  done < ${OLD_RULE_FILE} 
}

update_route () {
  log "Updating new route ..."
  echo "" > ${NEXTHOP_FILE}

  for PPP in ${PPP_LIST}
  do
    new_ppp=`cat ${TEMP_FILE} | grep ${PPP}`
    new_ip=`echo ${new_ppp} | cut -d':' -f2`
    new_tab=`echo ${new_ppp} | cut -d':' -f3`
  
    log "${IP} route add ${new_ip}/32 dev ${PPP} src ${new_ip} table ${new_tab}"
    ${IP} route add ${new_ip}/32 dev ${PPP} src ${new_ip} table ${new_tab}

    log "${IP} route add default via ${new_ip} table ${new_tab}"
    ${IP} route add default via ${new_ip} table ${new_tab}

    log "${IP} rule add from ${new_ip} table ${new_tab}"
    ${IP} rule add from ${new_ip} table ${new_tab}

    log "nexthop via ${new_ip} dev ${PPP} weight 1"
    echo "nexthop via ${new_ip} dev ${PPP} weight 1 " >> ${NEXTHOP_FILE} 2>&1
  done
}

update_default_route () {
  log "Updating default route ..."
  nexthop=`cat ${NEXTHOP_FILE}`
  check=`echo $nexthop | grep nexthop | wc -l`
  if [ $check -gt 0 ]; then 
    default_gw="${IP} route add default scope global equalize "
    log "${default_gw} ${nexthop}"
    ${IP} route del default
    ${default_gw} ${nexthop}

    # Game online and other ports 1025:65535 go through the specified game path
    if [ ${GAMEONLINE_ROUTE_TO_IFNO} -gt -1 ]; then
      log "Adding GameOnline interception ..."
      ${IP} rule del fwmark 4 table ${TABLE_PREFIX}${GAMEONLINE_ROUTE_TO_IFNO}
      ${IP} rule add fwmark 4 table ${TABLE_PREFIX}${GAMEONLINE_ROUTE_TO_IFNO}
    fi
  fi
}

### MAIN ###
changes=0

# Gathering current PPP list
PPP_LIST=`${IFCONFIG} | grep ppp | cut -d' ' -f1`
IF_COUNT=`${IFCONFIG} | grep ppp | cut -d' ' -f1 | wc -l`

for PPP in ${PPP_LIST}
do
  if_ip=`${IFCONFIG} ${PPP} | grep inet | cut -d':' -f2 | cut -d' ' -f 1`
  table_id=`echo ${PPP} | cut -d'p' -f4`
  check_old=`cat ${OLD_IF_FILE} | grep ${PPP}`
  check_ip=`echo ${check_old} | grep ${if_ip}`
  if [ $? -eq 1 ]; then
    # Some change in this device do update routing 
    log "${PPP} Routing change...."
    changes=1 
  fi
  echo ${PPP}:${if_ip}:${TABLE_PREFIX}${table_id} >> ${TEMP_FILE}
done

if [ -f ${OLD_IF_COUNT_FILE} ]; then
  OLD_IF_COUNT=`cat ${OLD_IF_COUNT_FILE}`
else
  OLD_IF_COUNT=0
fi

if [ ${OLD_IF_COUNT} != ${IF_COUNT} ]; then
  log "Links size changed!"
  changes=1
fi

if [ ${changes} -eq 1 ]; then
  del_old_rule
  update_route
  update_default_route
  
  ${IP} route flush cache

  if [ ${RELOAD_SQUID} -gt 0 ]; then
     log "Reloading SQUID config ..."
     ${SQUID} reload
  fi
  date >> ${REDIAL_LOG_FILE}

  success=`${IP} route | grep nexthop | wc -l`
  if [ ${success} -gt 0 ]; then
    cp ${TEMP_FILE} ${OLD_IF_FILE}
    echo ${IF_COUNT} > ${OLD_IF_COUNT_FILE}
    log "Updated!"
  else
    rm -f ${OLD_IF_FILE}
    rm -f ${OLD_IF_COUNT_FILE}
    log "Update Pending! - Retry in the next time."
  fi
fi

### END ###

Cron Job

nano /etc/cron.d/ppp-balance
*/1 *     * * *     root  /usr/local/bin/ppp-balance.sh >/dev/null 2>&1
/etc/init.d/cron restart