Recently I ran into a problem setting up two channels on the Internet on FreeBSD OS
Nothing absolutely complicated was supposed to, but I still had to read a lot of documentation.
Actually the task:
1. create a gateway with two Internet access, one main, another backup.
2. minimize the participation of a person in the change on the bey channel.
')
Instruments:
OS FreeBSD 6.x, PF, perl
Decision:
FreeBSD was shipped with minimal installation, the only change to make
This is to add the PF module to the kernel. This is all done is not difficult.
cp / usr / src / sys / i386 / conf / GENERIC / usr / src / sys / i386 / conf / PF
ee / usr / src / sys / i386 / conf / PFadd lines:
# Pf
device pf
device pflog
device pfsync# ALTQ
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_PRIQ
options ALTQ_NOPCCNext you need to save and rebuild the kernel:
cd / usr / src
make buildkernel KERNCONF = PF
make installkernel KERNKONF = PF
rebootAfter booting the system, you need to fix /etc/rc.conf
Add the following:
gateway_enable = "YES"
pf_enable = "YES" # Enable PF (load module if necessary)
pf_rules = "/ etc / pf.conf" # defining rules for pf
pf_flags = "" # additional flags to run pfctl
pflog_enable = "YES" # run pflogd (8)
pflog_logfile = "/ var / log / pflog" # where pflogd should save the log
pflog_flags = "" # additional flags to run pflogdsave
Next, you need to write the rules for PF:
ee /etc/pf.conf# Main Setting
ext_if_1 = "rl0" # IPS_1 - first channel interface
ext_if_2 = "rl1" # IPS_2 - interface of the second channel
int_if = "ae0" # lan - internal network interface
lo = "lo0" # loopback
int_net = "172.21.0.0/16" # LAN NETWORK
ext_addr_1 = "222.0.0.2" # IPS_1 wan
ext_addr_2 = "223.0.0.2" # IPS_2 wan
int_addr = "172.21.0.1" # LAN IP
gw_1 = "222.0.0.1" # IPS_1 gw
gw_2 = "223.0.0.1" # IPS_2 gw
# services
tcp_svc = "ssh" - allowed ports on external interfaces.
#log - packet logging
set loginterface ae0
set loginterface rl0
set loginterface rl1
# skip iface - do not filter the loopback,
# many services use this interface for system things.
set skip on lo0
# scrub
scrub in all
# NAT
# We are rubbing external interfaces
nat on $ ext_if_1 inet from! (self) -> ($ ext_if_1: 0) # IPS_1 nat
nat on $ ext_if_2 inet from! (self) -> ($ ext_if_2: 0) # IPS_2 nat
# BLOCK ALL
# Initially, you must block all incoming traffic
block in
# antispoof
antispoof quick for $ int_if
# ICMP
# enable icmp on external interfaces and route them to their gateways
# To avoid a situation, we ping one external address, and the answer goes to the second gateway.
# IPS_1
pass in on $ ext_if_1 reply-to ($ ext_if_1 $ gw_1) inet proto icmp to ($ ext_if_1) tag EXT_IF_A icmp-type echoreq code 0
pass in on $ ext_if_1 inet proto icmp from ($ ext_if_1: network) to ($ ext_if_1) icmp-type echoreq code 0
# IPS_2
pass in on $ ext_if_2 reply-to ($ ext_if_2 $ gw_2) inet proto icmp to ($ ext_if_2) tag EXT_IF_B icmp-type echoreq code 0
pass in on $ ext_if_2 inet proto icmp from ($ ext_if_2: network) to ($ ext_if_2) icmp-type echoreq code 0
# allow tcp ports
# we allow services on external interfaces and their routing; above, we only allow ssh
# for udp a similar entry for changing only proto tcp to proto udp
# IPS_1
pass in on $ ext_if_1 reply-to ($ ext_if_1 $ gw_1) inet proto tcp to ($ ext_if_1) port {$ tcp_svc}
pass in on $ ext_if_1 inet proto tcp from ($ ext_if_1: network) to ($ ext_if_1) port {$ tcp_svc}
# IPS_2
pass in on $ ext_if_2 reply-to ($ ext_if_2 $ gw_2) inet proto tcp to ($ ext_if_2) port {$ tcp_svc}
pass in on $ ext_if_2 inet proto tcp from ($ ext_if_2: network) to ($ ext_if_2) port {$ tcp_svc}
# INCOMING ROUTE
# route all incoming traffic, under the condition, if you come to that interface,
# send the response from the gateway
# plus tag. Tags will help us correctly forward ports,
# let's say we have a terminal server, you can forward it as follows
# rdr on $ ext_if_2 proto tcp from any to $ ext_addr_2 port 3389 tag EXT_IF_B -> 172.21.0.1 port 3389
# rdr on $ ext_if_1 proto tcp from any to $ ext_addr_1 port 3389 tag EXT_IF_A -> 172.21.0.1 port 3389
# IPS_1
pass in quick from ($ ext_if_1: network) tagged EXT_IF_A keep state
pass in quick reply-to ($ ext_if_1 $ gw_1) tagged EXT_IF_A keep state
# IPS_2
pass in quick from ($ ext_if_2: network) tagged EXT_IF_B keep state
pass in quick reply-to ($ ext_if_2 $ gw_2) tagged EXT_IF_B keep state
# FIREWALL
# allow everything in the internal space of the gateway
pass out inet from (self: network)
pass in inet proto icmp to (self: network)
# LOCAL NETWORK
# Allow all traffic to exit the local network
pass quick on $ int_if
# OUTGOING ROUTE
# Route outbound traffic
pass out route-to ($ ext_if_1 $ gw_1) inet from ($ ext_if_1) keep state
pass out route-to ($ ext_if_2 $ gw_2) inet from ($ ext_if_2) keep state
pass out inet from {$ ext_if_1 $ ext_if_2} to (self: network)
These rules are enough to ensure circulation on two channels, with the correct routing.
I will not go into details if you want to see what each rule means, then read the documentation for the PF.
Next, you need to add the main gateway to rc.conf:
ee /etc/rc.conf
defaultrouter = "222.0.0.1"
save
Next you need to put a bag for pearl
NET_PING :
cd / usr / ports / net / p5-net-ping
make installDale we write the script itself to switch channels in case of the main drop, and back in case of a raise.
Save the script, make it executable, and throw it into crowns for execution once a minute.
Everything. Reboot and everything should work for you.
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::Ping;
# 1 -
# 2 - .
my $action = 1;
my $p = Net::Ping->new("icmp");
my $host_gw = "222.0.0.1"; # default gw
my $gw = "223.0.0.1";
my $now = localtime time;
if($action == 1){
my $command = `netstat -rn | grep default`;
my @b = split('\s+',$command,3);
if ($p->ping($host_gw,0.05)){
print "host $host_gw is ok\n";
if($b[1] ne $host_gw){
if($b[1] eq ""){
`route add default 222.0.0.1`;
}else{
`route change default 222.0.0.1`;
open(LOG,">>/change_route.log");
print LOG "[!] $now Route change to 222.0.0.1\n";
close(LOG);
}
}
}else{
print "host $host_gw is bad.\n";
if($b[1] ne $gw){
`route change default 223.0.0.1`;
open(LOG,">>/change_route.log");
print LOG "[!] $now Route change to 223.0.0.1\n";
close(LOG);
}
}
$p->close();
}
if($action == 2){
my $command = `netstat -rn | grep default`;
my @b = split('\s+',$command,3);
if($b[1] ne $gw){
if($b[1] eq ""){
`route add default 223.0.0.1`;
}else{
`route change default 223.0.0.1`;
open(LOG,">>/change_route.log");
print LOG "[!] $now Route change to 223.0.0.1\n";
close(LOG);
}
}
}
original article