Sometimes you need your devices (say an SMTP server) to have a specific outbound public IP for things like reverse-DNS look-ups to ensure mail delivery and reputation, or maybe you want traffic from particular devices or policies to go out an IP for means of tracking.
It is not immediately obvious on Fortigates how to do this, typically, when you create a policy and NAT traffic out through it, the Fortigate will use its’ own public IP assigned by the ISP to originate the traffic from, if you have got a static IP and use an unnumbered address from your ISP then you might be lucky and your R-DNS might match this, however, in most cases you will have a separate Virtual IP for your SMTP server that is different to this and thus you need the R-DNS lookup to match that of the A-Record.
So the problem becomes: “How do I get traffic from a specific policy to originate from a static public IP of my choosing?”
Fortigates have a concept called IP Pools
.
IP Pools are a mechanism that allow sessions leaving the FortiGate Firewall to use NAT. An IP pool defines a single IP address or a range of IP addresses to be used as the source address for the duration of the session. These assigned addresses will be used instead of the IP address assigned to that FortiGate interface.
So we need to first create an IP Pool
in Policy & Objects -> Objects -> IP Pools
:
- Click
Create New
- Set the
Name
- Set the type to
Overload
(To allow multiple back-end devices to use this one public IP) - Set the
External IP Range
to be a single address in the block assigned by your ISP - Save
Next we need to go to Policies
in the Policy & Objects -> Policy -> IPv4
section and select the policy from LAN -> WAN
that contains our SMTP server and edit the Firewall/Network Options
section:
- Set
NAT
toON
- Choose
Use Dynamic IP Pool
- Specify the pool name you created before
- Save
Now any traffic going to WAN through this policy will be NAT’d through the IP Pool
address(es) you specified, thus, the outbound traffic from your SMTP server will originate from the same address as the R-DNS lookup for you domain’s A-Record and result in successful mail delivery.
Why not follow @mylesagray on Twitter for more like this!
Hello, oh this is awesome, but when I try this, the network connection goes down. This is basically a thing because I’ve got a routing table with X.Y.Z.129 address that is a gateway on another router… Is there a way I can achieve this with this routing?
X.Y.Z.0/24 – global IP class C
X.Y.Z.190 – BGP router ID
X.Y.Z.129 – address which should be used as “outgoing IP”, but for now it shows the ISP address
X.Y.Z.0/24 -> next-hop X.Y.Z.129 (second router, firewall)
10.0.0.0/8 -> next-hop 10.0.0.1
I should somehow change the routing on second router.
Address X.Y.Z.129 is available on the internet, but it is not used as outgoing ip…
Network goes down exactly when I only add the IP pool with X.Y.Z.129, so maybe I should connect next policy and maybe it would start?
Ok, I’ve tried to add this to pool, but the effect is the same – network goes down.
The routing goes like this:
BGP device X.Y.Z.190 = route dest X.Y.Z.0/24 next-hop X.Y.Z.129
FW device 10.0.0.1 = route dest 0.0.0.0 next-hop X.Y.Z.190
It looks like a routing loop? But it worked on Juniper, so maybe it about BGP next_hop, route_map parameters or something?
Hey, Fortinet order of operations is:
Routing -> Policies -> NAT
Can you detail a diagram of how this works logically as well as subnet positions?
Hello.
This is my FG routing table:
FG # get router info routing-table all | grep X.Y.Z.
B X.Y.Z.0/24 [20/0] is a summary, Null, 19:48:39
S X.Y.Z.0/26 [10/0] via X.Y.Z.129, port3
C X.Y.Z.128/26 is directly connected, port3
S X.Y.Z.240/29 [10/0] via X.Y.Z.129, port3
FG #
and BGP configuration:
config router bgp
set as 00000
set router-id X.Y.Z.190
set keepalive-timer 45
set holdtime-timer 120
set bestpath-med-missing-as-worst enable
set log-neighbour-changes enable
set graceful-restart enable
config aggregate-address
edit 1
set prefix X.Y.Z.0 255.255.255.0
set as-set enable
next
end
config neighbor
edit “3.3.3.33”
set description “ISP3”
set remote-as 33333
set send-community6 disable
set keep-alive-timer 45
set holdtime-timer 120
set connect-timer 60
set weight 50
next
edit “2.2.2.157”
set description “ISP2”
set remote-as 222222
set send-community6 disable
set keep-alive-timer 45
set holdtime-timer 120
set connect-timer 60
set weight 100
next
edit “1.1.1.161”
set next-hop-self enable
set description “ISP1”
set remote-as 11111
set send-community6 disable
set keep-alive-timer 45
set holdtime-timer 120
set connect-timer 60
set weight 250
next
end
config network
edit 1
set prefix X.Y.Z.0 255.255.255.0
next
end
config redistribute “connected”
end
config redistribute “rip”
end
config redistribute “ospf”
end
config redistribute “static”
set status enable
end
config redistribute “isis”
end
config redistribute6 “connected”
end
config redistribute6 “rip”
end
config redistribute6 “ospf”
end
config redistribute6 “static”
end
config redistribute6 “isis”
end
set graceful-stalepath-time 180
set graceful-update-delay 180
end
And here’s my old configuration, it is working correctly. The outgoing address is X.Y.Z.129, and SMTP server outgoing is X.Y.Z.189
interfaces {
ge-0/0/0 {
unit 0 {
family inet {
address 10.100.140.254/24;
}
}
}
ge-0/0/1 {
description INSITE;
unit 0 {
description INSITE_if;
family inet {
address X.Y.Z.190/26;
}
}
}
ge-0/0/2 {
description MultiPlay;
unit 0 {
description ISP2;
family inet {
address 2.2.2.158/30;
}
}
}
ge-0/0/3 {
description Netia;
unit 0 {
description ISP1;
family inet {
address 1.1.1.162/30;
}
}
}
lo0 {
unit 0 {
family inet {
address 127.0.0.1/32;
}
}
}
}
routing-options {
static {
route X.Y.Z.0/26 next-hop X.Y.Z.129;
route 10.0.0.0/8 next-hop 10.100.140.1;
route X.Y.Z.240/29 next-hop X.Y.Z.129;
}
aggregate {
route X.Y.Z.0/24;
}
router-id X.Y.Z.190;
autonomous-system XXXXX loops 1;
}
protocols {
bgp {
accept-remote-nexthop;
group NETIA {
type external;
export [ R_PUB_POLICY REJECT_ALL ];
neighbor 1.1.1.161 {
peer-as 11111;
}
}
group MULTIPLAY {
type external;
export [ R_PUB_POLICY REJECT_ALL ];
neighbor 2.2.2.157 {
peer-as 222222;
}
}
}
}
policy-options {
prefix-list R_PUB {
X.Y.Z.0/24;
}
policy-statement R_PUB_POLICY {
from {
protocol aggregate;
prefix-list R_PUB;
}
then accept;
}
policy-statement REJECT_ALL {
then reject;
}
}
security {
screen {
ids-option untrust-screen {
icmp {
ping-death;
}
ip {
source-route-option;
tear-drop;
}
tcp {
syn-flood {
alarm-threshold 1024;
attack-threshold 200;
source-threshold 1024;
destination-threshold 2048;
queue-size 2000;
timeout 20;
}
land;
}
}
}
zones {
security-zone trust {
tcp-rst;
host-inbound-traffic {
system-services {
all;
}
protocols {
all;
}
}
interfaces {
ge-0/0/0.0 {
host-inbound-traffic {
system-services {
http;
https;
ssh;
telnet;
dhcp;
}
}
}
ge-0/0/1.0;
ge-0/0/2.0 {
host-inbound-traffic {
system-services {
ping;
}
protocols {
bgp;
}
}
}
ge-0/0/3.0 {
host-inbound-traffic {
system-services {
ping;
}
protocols {
bgp;
}
}
}
}
}
security-zone untrust {
screen untrust-screen;
host-inbound-traffic {
system-services {
all;
}
protocols {
all;
}
}
}
}
policies {
from-zone trust to-zone trust {
policy default-permit {
match {
source-address any;
destination-address any;
application any;
}
then {
permit;
}
}
}
from-zone trust to-zone untrust {
policy ban-ntp {
match {
source-address any;
destination-address any;
application [ junos-nntp junos-ntp junos-ms-sql ];
}
then {
deny;
}
}
policy default-permit {
match {
source-address any;
destination-address any;
application any;
}
then {
permit;
}
}
}
from-zone untrust to-zone trust {
policy ban-ntp {
match {
source-address any;
destination-address any;
application [ junos-ntp junos-nntp junos-ms-sql ];
}
then {
deny;
}
}
policy default-deny {
match {
source-address any;
destination-address any;
application any;
}
then {
permit;
}
}
}
default-policy {
deny-all;
}
}
}
Ok, I’ve managed to figure it out… just needed to disable NAT, r0fl. Thank you for replies!
thank you working perfect for my customer
Hey guys, good post. was looking for the same for a PBX.
now, where do you configure the IP on the WAN interface, for the incoming rules?
as a “secondary IP”? on the interface?
Virtual IP.
Policy & Objects->Virtual IPs