NAME
Net::ISP::Balance - Support load balancing across multiple internet service providers
SYNOPSIS
use Net::ISP::Balance;
# initialize the module with its configuration file
my $bal = Net::ISP::Balance->new('/etc/network/balance.conf');
$bal->verbose(1); # verbosely print routing and firewall
# commands to STDERR before running them.
$bal->echo_only(1); # echo commands to STDOUT; don't execute them.
# mark the balanced services that are up
$bal->up('CABLE','DSL','SATELLITE');
# write out routing and firewall commands
$bal->set_routes_and_firewall();
# write out a forwarding rule
$bal->forward(80 => '192.168.10.35'); # forward web requests to this host
# write out an arbitrary routing rule
$bal->ip_route('add 192.168.100.1 dev eth0 src 198.162.1.14');
# write out an arbitrary iptables rule
$bal->iptables('-A INCOMING -p tcp --dport 6000 -j REJECT');
# get information about all services
my @s = $bal->service_names;
for my $s (@s) {
print $bal->dev($s);
print $bal->ip($s);
print $bal->gw($s);
print $bal->net($s);
print $bal->fwmark($s);
print $bal->table($s);
print $bal->running($s);
}
FREQUENTLY-USED METHODS
Here are the class methods for this module that can be called on the class name.
$bal = Net::ISP::Balance->new('/path/to/config_file.conf','/path/to/interfaces');
Creates a new balancer object.
The first optional argument is the balancer configuration file, which defaults to /etc/network/balance.conf on Ubuntu/Debian-derived systems, and /etc/sysconfig/network-scripts/balance.conf on RedHat/CentOS-derived systems. From hereon, we'll refer to the base of the various configuration files as $ETC_NETWORK.
The second optional argument is the system network interfaces file, defaulting to $ETC_NETWORK/interfaces.
$bal->set_routes_and_firewall
Once the Balance objecty is created, call set_routes_and_firewall() to configure the routing tables and firewall for load balancing. These rules will either be executed on the system, or printed to standard output as a series of shell script commands if echo_only() is set to true.
The routing tables and firewall rules are based on the configuration described in balance.conf (usually /etc/network/balance.conf or /etc/sysconfig/network-scripts/balance.conf). You may add custom routes and rules by creating files in /etc/network/balance/routes and /etc/network/balance/firewall (/etc/sysconfig/network-scripts/balance/{routes,firewalls} on RedHat/CentOS systems). The former contains a series of files or perl scripts that define additional routing rules. The latter contains files or perl scripts that define additional firewall rules.
Any files you put into these directories will be read in alphabetic order and added to the routes and/or firewall rules emitted by the load balancing script.Contained in this directory are subdirectories named "routes" and "firewall". The former contains a series of files or perl scripts that define additional routing rules. The latter contains files or perl scripts that define additional firewall rules.
Any files you put into these directories will be read in alphabetic order and added to the routes and/or firewall rules emitted by the load balancing script.
A typical routing rules file will look like the example shown below.
# file: /etc/network/balance/01.my_routes
ip route add 192.168.100.1 dev eth0 src 198.162.1.14
ip route add 192.168.1.0/24 dev eth2 src 10.0.0.4
Each line will be sent to the shell, and it is intended (but not required) that these be calls to the "ip" command. General shell scripting constructs are not allowed here.
A typical firewall rules file will look like the example shown here:
# file: /etc/network/firewall/01.my_firewall_rules
# accept incoming telnet connections to the router
iptable -A INPUT -p tcp --syn --dport telnet -j ACCEPT
# masquerade connections to the DSL modem's control interface
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
You may also insert routing and firewall rules via fragments of Perl code, which is convenient because you don't have to hard-code any network addresses and can make use of a variety of shortcuts. To do this, simply end the file's name with .pl and make it executable.
Here's an example that defines a series of port forwarding rules for incoming connections:
# file: /etc/network/firewall/02.forwardings.pl
$B->forward(80 => '192.168.10.35'); # forward port 80 to internal web server
$B->forward(443=> '192.168.10.35'); # forward port 443 to
$B->forward(23 => '192.168.10.35:22'); # forward port 23 to ssh on web sever
The main thing to know is that on entry to the script the global variable $B will contain an initialized instance of a Net::ISP::Balance object. You may then make method calls on this object to emit firewall and routing rules.
A typical routing rules file will look like the example shown below.
# file: /etc/network/balance/01.my_routes
ip route add 192.168.100.1 dev eth0 src 198.162.1.14
ip route add 192.168.1.0/24 dev eth2 src 10.0.0.4
Each line will be sent to the shell, and it is intended (but not required) that these be calls to the "ip" command. General shell scripting constructs are not allowed here.
A typical firewall rules file will look like the example shown here:
# file: /etc/network/firewall/01.my_firewall_rules
# accept incoming telnet connections to the router
iptable -A INPUT -p tcp --syn --dport telnet -j ACCEPT
# masquerade connections to the DSL modem's control interface
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
You may also insert routing and firewall rules via fragments of Perl code, which is convenient because you don't have to hard-code any network addresses and can make use of a variety of shortcuts. To do this, simply end the file's name with .pl and make it executable.
Here's an example that defines a series of port forwarding rules for incoming connections:
# file: /etc/network/firewall/02.forwardings.pl
$B->forward(80 => '192.168.10.35'); # forward port 80 to internal web server
$B->forward(443=> '192.168.10.35'); # forward port 443 to
$B->forward(23 => '192.168.10.35:22'); # forward port 23 to ssh on web sever
The main thing to know is that on entry to the script the global variable $B will contain an initialized instance of a Net::ISP::Balance object. You may then make method calls on this object to emit firewall and routing rules.
$verbose = $bal->verbose([boolean]);
sub bal_conf_file { my $self = shift; my $d = $self->{bal_conf_file}; $self->{bal_conf_file} = shift if @_; $d; } Get/set verbosity of the module. If verbose is true, then firewall and routing rules will be echoed to STDERR before being executed on the system.
$echo = $bal->echo_only([boolean]);
Get/set the echo_only flag. If this is true (default false), then routing and firewall rules will be printed to STDOUT rathar than being executed.
$result_code = $bal->sh(@args)
Pass @args to the shell for execution. If echo_only() is set to true, the command will not be executed, but instead be printed to standard output.
Example:
$bal->sh('ip rule flush');
The result code is the same as CORE::system().
$bal->iptables(@args), but not executed.
Invoke sh() to call "iptables @args".
Example:
$bal->iptables('-A OUTPUT -o eth0 -j DROP');
You may pass an array reference to iptables(), in which case iptables is called on each member of the array in turn.
Example:
$bal->iptables(['-P OUTPUT DROP',
'-P INPUT DROP',
'-P FORWARD DROP']);
Note that the method keeps track of rules; if you try to enter the same iptables rule more than once the redundant ones will be ignored.
$bal->forward($incoming_port,$destination_host,@protocols)
This method emits appropriate port/host forwarding rules. Destination host can accept any of these forms:
192.168.100.1 # forward to same port as incoming
192.168.100.1:8080 # forward to a different port on host
Protocols are one or more of 'tcp','udp'. If omitted defaults to tcp.
Examples:
$bal->forward(80 => '192.168.100.1');
$bal->forward(80 => '192.168.100.1:8080','tcp');
$bal->ip_route(@args)
Shortcut for $bal->sh('ip route',@args);
$bal->ip_rule(@args)
Shortcut for $bal->sh('ip rule',@args);
$verbose = $bal->iptables_verbose([boolean])
Makes iptables send an incredible amount of debugging information to syslog.
QUERYING THE CONFIGURATION
These methods allow you to get information about the Net::ISP::Balance object's configuration, including settings and other characteristics of the various network interfaces.
@names = $bal->service_names
Return the list of service names defined in balance.conf.
@names = $bal->isp_services
Return list of service names that correspond to load-balanced ISPs.
@names = $bal->lan_services
Return list of service names that correspond to lans.
@up = $bal->up(@up_services)
Get or set the list of ISP interfaces that are currently active and should be used for balancing.
$services = $bal->services
Return a hash containing the configuration information for each service. The keys are the service names. Here's an example:
{
0 HASH(0x91201e8)
'CABLE' => HASH(0x9170500)
'dev' => 'eth0'
'fwmark' => 2
'gw' => '191.3.88.1'
'ip' => '191.3.88.152'
'net' => '191.3.88.128/27'
'ping' => 'www.google.ca'
'role' => 'isp'
'running' => 1
'table' => 2
'DSL' => HASH(0x9113e00)
'dev' => 'ppp0'
'fwmark' => 1
'gw' => '112.211.154.198'
'ip' => '11.120.199.108'
'net' => '112.211.154.198/32'
'ping' => 'www.google.ca'
'role' => 'isp'
'running' => 1
'table' => 1
'LAN' => HASH(0x913ce58)
'dev' => 'eth1'
'fwmark' => undef
'gw' => '192.168.10.1'
'ip' => '192.168.10.1'
'net' => '192.168.10.0/24'
'ping' => ''
'role' => 'lan'
'running' => 1
}
$service = $bal->service('CABLE')
Return the subhash describing the single named service (see services() above).
$dev = $bal->dev('CABLE')
$ip = $bal->ip('CABLE')
$gateway = $bal->gw('CABLE')
$network = $bal->net('CABLE')
$role = $bal->role('CABLE')
$running = $bal->running('CABLE')
$mark_number = $bal->fwmark('CABLE')
$routing_table_number = $bal->table('CABLE')
$ping_dest = $bal->ping('CABLE')
These methods pull out the named information from the configuration data. fwmark() returns a small integer that will be used for marking connections for routing through one of the ISP connections when an outgoing connection originates on the LAN and is routed through the router. table() returns a small integer corresponding to a routing table used to route connections originating on the router itself.
FILES AND PATHS
These are methods that determine where Net::ISP::Balance finds its configuration files.
$path = Net::ISP::Balance->install_etc
Returns the path to where the network configuration files reside on this system, e.g. /etc/network. Note that this only knows about Ubuntu/Debian-style network configuration files in /etc/network, and RedHat/CentOS network configuration files in /etc/sysconfig/network-scripts.
$file = Net::ISP::Balance->default_conf_file
Returns the path to the default configuration file, $ETC_NETWORK/balance.conf.
$file_or_dir = Net::ISP::Balance->default_interface_file
Returns the path to the place where the system stores its network configuration information. On Ubuntu/Debian-derived systems, this will be the file /etc/network/interfaces. On RedHad/CentOS-derived systems, this is the directory named /etc/sysconfig/network-scripts/ which contains a series of ifcfg-* files.
$dir = Net::ISP::Balance->default_rules_directory
Returns the path to the directory where the additional router and firewall rules are stored. On Ubuntu-Debian-derived systems, this is /etc/network/balance/. On RedHat/CentOS systems, this is /etc/sysconfig/network-scripts/balance/.
$file = Net::ISP::Balance->default_lsm_conf_file
Returns the path to the place where we should store lsm.conf, the file used to configure the lsm (link status monitor) application.
On Ubuntu/Debian-derived systems, this will be the file /etc/network/lsm.conf. On RedHad/CentOS-derived systems, this will be /etc/sysconfig/network-scripts/lsm.conf.
$dir = Net::ISP::Balance->default_lsm_scripts_dir
Returns the path to the place where lsm stores its helper scripts. On Ubuntu/Debian-derived systems, this will be the directory /etc/network/lsm/. On RedHad/CentOS-derived systems, this will be /etc/sysconfig/network-scripts/lsm/.
$file = $bal->bal_conf_file([$new_file])
Get/set the main configuration file path, balance.conf.
$dir = $bal->rules_directory([$new_rules_directory])
Get/set the route and firewall rules directory.
$file = $bal->lsm_conf_file([$new_conffile])
Get/set the path to the lsm configuration file.
$dir = $bal->lsm_scripts_dir([$new_dir])
Get/set the path to the lsm scripts directory.
INFREQUENTLY-USED METHODS
These are methods that are used internally, but may be useful to applications developers.
$lsm_config_text = $bal->lsm_config_file(-warn_email=>'root@localhost')
This method creates the text used to create the lsm.conf configuration file. Pass it a series of -name=>value pairs to incorporate into the file.
Possible switches and their defaults are:
-checkip 127.0.0.1
-eventscript /etc/network/lsm/balancer_event_script
-notifyscript /etc/network/lsm/default_script
-max_packet_loss 15
-max_successive_pkts_lost 7
-min_packet_loss 5
-min_successive_pkts_rcvd 10
-interval_ms 1000
-timeout_ms 1000
-warn_email root
-check_arp 0
-sourceip <autodiscovered>
-device <autodiscovered>
-ttl 0 <use system value>
-status 2 <no assumptions>
-debug 8 <moderate verbosity from scale of 0 to 100>
$info = $bal->get_ppp_info($dev)
This nmethod returns a hashref containing information about a PPP network interface device, including IP address, gateway, network, and netmask. The $dev argument is a standard Linux network device name such as "ppp0".
$info = $bal->get_static_info($deb)
This nmethod returns a hashref containing information about a statically-defined network interface device, including IP address, gateway, network, and netmask. The $dev argument is a standard Linux network device name such as "etho0".
$info = $bal->get_dhcp_info($deb)
This nmethod returns a hashref containing information about a network interface device that is configured via dhcp, including IP address, gateway, network, and netmask. The $dev argument is a standard Linux network device name such as "eth0".
$path = $bal->find_dhclient_leases($dev)
This method finds the dhclient configuration file corresponding to DHCP-managed device $dev. The device is a standard device name such as "eth0".
$bal->set_routes()
This method is called by set_routes_and_firewall() to emit the rules needed to create the load balancing routing tables.
$bal->set_firewall
This method is called by set_routes_and_firewall() to emit the rules needed to create the balancing firewall.
$bal->enable_forwarding($boolean)
$bal->routing_rules()
This method is called by set_routes() to emit the rules needed to create the routing rules.
$bal->local_routing_rules()
This method is called by set_routes() to process the fules and emit the commands contained in the customized route files located in $ETC_DIR/balance/routes.
$bal->local_fw_rules()
This method is called by set_firewall() to process the fules and emit the commands contained in the customized route files located in $ETC_DIR/balance/firewall.
$bal->base_fw_rules()
This method is called by set_firewall() to set up basic firewall rules, including default rules and reporting.
$bal->balancing_fw_rules()
This method is called by set_firewall() to set up the mangle/fwmark rules for balancing outgoing connections.
$bal->sanity_fw_rules()
This is called by set_firewall() to create a sensible series of firewall rules that seeks to prevent spoofing, flooding, and other antisocial behavior. It also enables UDP-based network time and domain name service.
$bal->nat_fw_rules()
This is called by set_firewall() to set up basic NAT rules for lan traffic over ISP
BUGS
Please report bugs to GitHub: https://github.com/lstein/Net-ISP-Balance.
AUTHOR
Copyright 2014, Lincoln D. Stein (lincoln.stein@gmail.com)
Senior Principal Investigator, Ontario Institute for Cancer Research
LICENSE
This package is distributed under the terms of the Perl Artistic License 2.0. See http://www.perlfoundation.org/artistic_license_2_0.