Skip to content

Instantly share code, notes, and snippets.

@justincjahn
Created July 26, 2012 23:08
Show Gist options
  • Select an option

  • Save justincjahn/3185160 to your computer and use it in GitHub Desktop.

Select an option

Save justincjahn/3185160 to your computer and use it in GitHub Desktop.
FortiGate: Generate NAT configuration from given parameters.
#!/usr/bin/env perl -w
use strict;
use Getopt::Long;
use Pod::Usage;
# Configuration
my %config = (
'name' => undef,
'externalIp' => undef,
'internalIp' => undef,
'internalInet' => 'zInternal',
'externalInet' => 'port40'
);
# VARIABLES
## ADDRESS_NAME: The name of the firewall address rule.
## POOL_NAME: The name of the VIP Pool to create.
## VIP_NAME: The name of the VIP configuration.
## INTERNAL_INTERFACE: The internal interface of the client.
## EXTERNAL_INTERFACE: The name of the external interface.
## EXTERNAL_IP: The external IP address to assign to the user.
## INTERNAL_IP: The internal IP address of the client.
my $sTemplate = <<END;
config firewall address
edit "{ADDRESS_NAME}"
set associated-interface "{INTERNAL_INTERFACE}"
set subnet {INTERNAL_IP} 255.255.255.255
end
config firewall ippool
edit "{POOL_NAME}"
set endip {EXTERNAL_IP}
set startip {EXTERNAL_IP}
end
config firewall vip
edit "{VIP_NAME}"
set extip {EXTERNAL_IP}
set extintf "{EXTERNAL_INTERFACE}"
set mappedip {INTERNAL_IP}
end
config firewall policy
edit 0
set srcintf "{EXTERNAL_INTERFACE}"
set dstintf "{INTERNAL_INTERFACE}"
set srcaddr "any"
set dstaddr "{VIP_NAME}"
set action accept
set ippool enable
set poolname "{POOL_NAME}"
set schedule "always"
set service "ANY"
set nat enable
next
edit 0
set srcintf "{INTERNAL_INTERFACE}"
set dstintf "{EXTERNAL_INTERFACE}"
set srcaddr "{ADDRESS_NAME}"
set dstaddr "any"
set action accept
set ippool enable
set poolname "{POOL_NAME}"
set schedule "always"
set service "ANY"
set nat enable
end
END
# Attempt to fetch options from the command line. If they aren't set, then the
# code below will interactively prompt the user.
my $bHelp, my $bError = 0;
my $iOptions = GetOptions(
'external|x=s' => \$config{'externalIp'},
'internal|i=s' => \$config{'internalIp'},
'name|n=s' => \$config{'name'},
'if-internal=s' => \$config{'internalInet'},
'if-external=s' => \$config{'externalInet'},
'help|?' => \$bHelp
) or pod2usage(1);
# Handle required options
$bError = 1 if (!defined $config{'externalIp'});
$bError = 1 if (!defined $config{'internalIp'});
$bError = 1 if (!defined $config{'name'});
# If the user requested the help, or there was an error, let's display info
pod2usage(-exitstatus => 0, -verbose => 2) if ($bHelp);
pod2usage(1) if ($bError);
#
# NAME
#
chomp($config{'name'});
$config{'name'} =~ s/[\s,\.;:_`]+//g;
$config{'name'} = ucfirst($config{'name'});
#
# EXTERNAL IP
#
chomp($config{'externalIp'});
if (!($config{'externalIp'} =~ m/\d{2,}\.\d{1,}\.\d{1,}\.\d{1,}/)) {
print STDERR "External IP Address was invalid.\n";
exit(1);
}
#
# INTERNAL IP
#
chomp($config{'internalIp'});
if (!($config{'internalIp'} =~ m/\d{2,}\.\d{1,}\.\d{1,}\.\d{1,}/)) {
print STDERR "Internal IP Address was invalid.\n";
exit(1);
}
#
# EXTERNAL INTERFACE
#
chomp($config{'externalInet'});
if (!($config{'externalInet'} =~ m/[a-zA-Z0-9]+/)) {
print STDERR "Invalid external interface or zone supplied.\n";
exit(1);
}
#
# INTERNAL INTERFACE
#
chomp($config{'internalInet'});
if (!($config{'internalInet'} =~ m/[a-zA-Z0-9]+/)) {
print STDERR "Invalid internal interface or zone supplied.\n";
exit(1);
}
# Start replacing placeholders
my $sAddressName = 'n' . $config{'name'};
my $sPoolName = 'pool' . $config{'name'};
my $sVIPName = 'v' . $config{'name'};
$sTemplate =~ s/{ADDRESS_NAME}/$sAddressName/g;
$sTemplate =~ s/{POOL_NAME}/$sPoolName/g;
$sTemplate =~ s/{VIP_NAME}/$sVIPName/g;
$sTemplate =~ s/{INTERNAL_INTERFACE}/$config{'internalInet'}/g;
$sTemplate =~ s/{EXTERNAL_INTERFACE}/$config{'externalInet'}/g;
$sTemplate =~ s/{EXTERNAL_IP}/$config{'externalIp'}/g;
$sTemplate =~ s/{INTERNAL_IP}/$config{'internalIp'}/g;
# Print to STDOUT so that we can use output redirection
print STDOUT $sTemplate;
#
# DOCUMENTATION
#
__END__
=head1 NAME
nat.pl - NAT and SNAT Generator
=head1 SYNOPSIS
nat.pl -x I<ExternalIP> -i I<InternalIP> >> output.txt
Options:
--help Display additional information.
=head1 DESCRIPTION
nat.pl generates FortiOS NAT and SNAT configuration.
=head2 Parameters
=over 8
=item -n|--name
A name that describes the rule's purpose. Eg. lunchbox, justinsLaptop.
=item -x|--external
The external IP address to give the server. Should be a publically routable IP.
=item -i|--internal
The internal IP address of the server. Should be a private IP address.
=item --if-internal
The internally facing interface or zone. Defaults to zInternal.
=item --if-external
The WAN interface or zone. Defaults to port40.
=back
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment