Tuesday, 22 December 2015

SSH Rotary option

https://blog.initialdraft.com/archives/2377/

Let’s imagine we are asked to configure Router1 to run SSH access using the port 2009.
As we already know, SSH uses the tcp port 22 by default. So, how can we change the port that R1 uses to listen for SSH connections? There is a way to do it straightforward, with a configuration only in R1. This feature is called SSH rotary.
Let’s see how to configure it, the first thing we have to do is to generate the RSA key pair for the router with the command crypto key generate rsa. But first, we need to configure the hostname and the domain-name server in the router:
router(config)# hostname R1
R1(config)# ip domain name cisco.com
R1(config)# crypto key generate rsa
The name for the keys will be: R1.cisco.com
Choose the size of the key modulus in the range of 360 to 2048 for your
  General Purpose Keys. Choosing a key modulus greater than 512 may take
  a few minutes.
How many bits in the modulus [512]: 1024
% Generating 1024 bit RSA keys, keys will be non-exportable...[OK]
Once we have created the RSA key pair, it’s necessary to configure the user and password to access the router, and to apply it into the VTY line settings:
R1(config)# username cisco password CISCO
R1(config)# line vty 0 4
R1(config-line)# login local
Now, we will configure the router to expect ssh connections on port 2009. This is done with the command ip ssh port and applying arotary group. Then, that rotary group is configured on the VTY lines:
R1(config)# ip ssh port 2009 rotary 1
R1(config)# line vty 0 4
R1(config-line)# rotary 1
Let’s verify that the configuration its actually working:
R1#ssh -l cisco -p 2009 2.2.2.1

Password:

R1>sh tcp brief
TCB       Local Address               Foreign Address             (state)
66CCF71C  2.2.2.1.18922               2.2.2.1.2009                ESTAB
66CCFC78  2.2.2.1.2009                2.2.2.1.18922               ESTAB
So here you have it, how to configure a router to be accesed via SSH with a non-by-default port.

OSPF Forward Address

In Normal Areas:


http://www.costiser.ro/2013/05/26/ospf-understanding-the-forwarding-address-fa/

In the beginning, let’s see why FA (Forwarding Address) exists in the first place. We all know that packets destined to external destinations are routed through the advertising ASBR. According to RFC 2328 (see page 141), there might be situations when this behaviour is not desirable and they introduced the concept of FA in order to avoid extra hops in the path.
Consider the diagram below, where both RT-A and RT-B are connected to RT-X (a partner company), but only RT-A speaks eBGP with partner company (let’s say that RT-B does not have enough memory to run BGP). RT-A redistributes the BGP routes (ex: 172.16.10.0/24) into the OSPF domain, thus becoming an ASBR.
Common_problem_without_FA

Without the concept of FA, traffic from RT-B towards those external destinations will go via the ASBR (RT-A), as shown in the traceroute output.
If RT-A set FA = 192.168.1.3, then RT-B would route directly to FA instead of ASBR, as you can see below:
traceroutes_with_and_without_FA
Now, let’s see what are the conditions required to have a non-zero FA. According to Cisco documentation, all of these conditions need to be true:
  • 1. OSPF is enabled on the ASBR’s next hop interface AND
  • 2. ASBR’s next hop interface is non-passive under OSPF AND
  • 3. ASBR’s next hop interface is not point-to-point AND
  • 4. ASBR’s next hop interface is not point-to-multipoint AND
  • 5. ASBR’s next hop interface address falls under the network range specified in the router ospf command
Note the AND logical operator between each condition. An easier way to remember this: next-hop interface must be a broadcast interface that is natively advertised in OSPF.
- See more at: http://www.costiser.ro/2013/05/26/ospf-understanding-the-forwarding-address-fa/#sthash.69acUFQA.dpuf

IN NSSA AREAS:

he selection process is to choose the highest IP of a loopback advertised
into the NSSA area. If no loopback is advertised then choose the highest
physical interface IP advertised into the NSSA area.
I hope that I have provide another piece to the OSPF puzzle and you now have
a good understanding of the forwarding address.


BGP Regular Expressions

Filtering based on the AS_PATH attribute is done using BGP regular expressions.
Regular expressions are matched against the AS_PATH strings. Remember that
AS_PATH can be constructed of the following elements: AS_SET (unordered list of
AS numbers), AS_SEQUENCE (ordered list of AS numbers), AS_CONFED_SET,
and AS_CONFED_SEQUENCE, which are the same elements but consist of the
confederation AS numbers. For the purpose of matching, the AS_PATH attribute is
viewed as a string starting with the adjacent AS number on the leftmost position,
and the originating AS number in the rightmost position. When matching the
AS_SET attribute, enclose the AS numbers in curly brackets and separate them
with commas; for example, {100,200,300}. When matching a confederation path,
enclose the AS numbers in parentheses, using backslashes to escape the special
meaning of the character: “\(100\)”.

We will discuss the most useful types of regexp patterns suitable for many “real-life”
situations. You may read more about BGP regular expressions basics in our blog
post Understanding BGP Regular Expressions. First, recall the basic regular
expression meta-characters or modifiers:
1. “.” – any character
2. “?” – repeat the previous character one or zero times
3. “*” – repeat the previous character zero or any times
4. “+” – repeat the previous character one or more times
5. “^” – match the beginning of a string
6. “$” – match the end of a string
7. “[]” – range or elements
8. “_” – match the “space” separating AS numbers OR the end of the AS_PATH list


Other important regexp features include grouping and back-referencing. You can
use parentheses to group AS numbers, such as (123 124 1+), and every group is
assigned a number starting from left to right. For example, in the string “1 2 (3 4) 5 6
(7 8)”, the first group is assigned the number 1 and the second group number 2. You
can later “recall” the grouping by using the commands \1, \2, and so on for the group
numbers. For example, the string “(1 2) 3 \1” would match “1 2 3 1 2”. You may use
the pipe character “|” in addition to the grouping characters for the concept of
alternation. For example, (1 2)|(5 6) would match “1 2” or “5 6”. Now the practical
examples:
“^$” - means an empty AS_PATH attribute, which identifies the prefixes advertised
in the local AS.
“^254_” - means prefixes received from the directly adjacent AS 254. Note that
using “_” is important, because there could be another adjacent AS with the number
starting with 254.
“_254_” - prefixes transiting AS 254. The “_” characters are needed to clearly
separate the AS number.
“_254$” - means prefixes originated in the AS 254. This expression matches the
rightmost position in the string, meaning that the expression could be of arbitrary
length.
“^([0-9]+)_254” - routes from the AS 254 when it’s just “one-hop” away.
“^254_([0-9]+)” - prefixes from the clients of the directly connected AS 254.
“^(254_)+([0-9]+)” - prefixes from the clients of the adjacent AS 254, accounting for
the fact that AS 254 may do AS_PATH prepending.
“^254_([0-9]+_)+” - prefixes from the clients of the adjacent AS 254, accounting for
the fact that the clients may do AS_PATH prepending.
^\(65100\) - prefixes learned from the confederation peer 65100.
You configure BGP regular-expression using the IP AS-PATH access-lists:
ip as-path access-list <N> {permit|deny} <Regexp> . This access-list might be applied
as a filter-list to a peer using the syntax: neighbor <IP> filter-list <N> [in|out] .
However, the best approach is to match AS_PATH access-lists under a route-map

applied to the peer ( match as-path ),

Monday, 21 December 2015

BGP Access-list Prefix-List Distribute-list

Order of preference
For inbound updates:
1. route-map
2. filter-list
3. prefix-list OR distribute-list
For outbound updates:
1. prefix-list OR distribute-list
2. filter-list
3. route-map

Prefix-List:

ip prefix-list <NAME>seq <Num> {permit|deny} <Subnet>/<Prefix > [ge <Length1>] [le

<Length2>]


Can be used in 2 ways.

Way 1:

ip prefix-list BLOCK_222 deny 222.22.2.0/24
ip prefix-list BLOCK_222 permit 0.0.0.0/0 le 32
!
router bgp 200
neighbor 192.10.1.254 prefix-list BLOCK_222 in

Way 2:

ip prefix-list SHORTER_THAN_22 permit 0.0.0.0/0 le 22
!
route-map FROM_R9 permit 100
match ip address prefix-list SHORTER_THAN_22
!
router bgp 300
neighbor 155.1.79.9 route-map FROM_R9 in

Standar Access-List:

Way 1:

R2 so that it does not accept any prefix with the address 222.22.2.0 from R10:

ip access-list standard BLOCK_222
deny 222.22.2.0
permit any
!
router bgp 200
neighbor 192.10.1.254 distribute-list BLOCK_222 in

ip access-list standard ODD_FIRST_OCTET
permit 1.0.0.0 254.255.255.255
!
route-map FROM_R9 permit 100
match ip address ODD_FIRST_OCTET
!
router bgp 300
neighbor 155.1.79.9 route-map FROM_R9 in

Way 2:

Configure a standard access-list on R7 so that it does not accept any prefixes with
an even number in the first octet from R9

R7
ip access-list standard ODD_FIRST_OCTET
permit 1.0.0.0 254.255.255.255
!
route-map FROM_R9 permit 100
match ip address ODD_FIRST_OCTET
!
router bgp 300
neighbor 155.1.79.9 route-map FROM_R9 in


Extended Access-Lists:

Extended access-lists add more functionality to BGP prefixes filtering. In addition to
matching the subnet numbers, they also allow for subnet mask matching. A typical
extended access-list entry in the format permit {proto} <src-subnet> <src-mask> <dstsubnet>
<dst-mask> [options] is treated as follows. First, the protocol field and other
options are ignored. Next, the <src-subnet> <src-mask> pair is used to build an
expression for prefix subnet matching. The pair <dst-subnet> <dst-mask> is used as
an expression to match prefixes subnet mask.

permit ip 10.0.0.0 0.0.0.0 255.255.0.0 0.0.0.0 - matches 10.0.0.0/16 - Only
permit ip 10.0.0.0 0.0.0.0 255.255.255.0 0.0.0.0 - matches 10.0.0.0/24 - Only
permit ip 10.1.1.0 0.0.0.0 255.255.255.0 0.0.0.0 - matches 10.1.1.0/24 - Only
permit ip 10.0.0.0 0.0.255.0 255.255.255.0 0.0.0.0 - matches 10.0.X.0/24 - Any
permit ip 10.0.0.0 0.255.255.255 255.255.255.0 0.0.0.255 - matches 10.X.X.X/24 to
10.X.X.X/32 - Any number in the second, third, and fourth octet of the network with a
/24 to /32 subnet mask
permit ip 10.0.0.0 0.255.255.255 255.255.255.128 0.0.0.127 - matches 10.X.X.X/25 to
10.X.X.X/32 - Any number in the second, third, and fourth octet of the network with a
/25 to /32 subnet mask

Ex:

Configure an extended access-list on R7 as follows:
It does not accept any prefixes with an even third octet and with a subnet mask greater than or equal to /22 from R9.
This list should apply directly to the neighbor

R7:
ip access-list extended EVEN_3RD_MASK_GT_22
deny ip 0.0.0.0 255.255.254.255 255.255.252.0 0.0.3.255
permit ip any any
!
router bgp 300
neighbor 155.1.79.9 distribute-list EVEN_3RD_MASK_GT_22 in


BGP Conditional Advertisement

BGP Conditional Advertisement

BGP, by default, advertises all the best paths in its BGP table to external peers. Sometimes, it might be required that BGP advertises some paths conditionally, meaning, advertise paths only if some other routes are available. 

Conditional advertisement has two forms- advertisement of some prefix(es) when some other prefix(es) do not exist and advertisement of some prefix(es) when some other prefix(es) exist. The prefixes to be advertised are defined by advertise-map. The condition is defined by a route-map called non-exist-map for conditions that do not exist or by a route-map called exist-map for conditions that do exist.

The first form of conditional advertisement is configured as follows-

neighbor <neighbor-ip-address> advertise-map <map1> non-exist-map <map2>

The map2 route-map tracks the prefix(es) in the local router. If a match is made, the status of the non-exist-map is Withdraw; when no match is made, the status is Advertise.

The map1 route-map defines the prefix(es) that are to be advertised when the status of non-exist-map is Advertise. When the status of the non-exist-map isWithdraw, the prefix(es) in advertise-map are not advertised.

The second form of conditional advertisement is configured as follows-
neighbor <neighbor-ip-address> advertise-map <map1> exist-map <map2>

Again, the map2 route-map tracks the prefix(es) in the local router. If a match is made, the status of the exist-map is Advertise; when no match is made, the status of the exist-map is Withdraw. The function is map1 route-map is same as above.

BGP Maps

BGP Aggregation - Attribute-Map:
========================

R8#show ip bgp 112.0.0.0 255.0.0.0
BGP routing table entry for 112.0.0.0/8, version 49 Paths: (1 available, best #1, table default,
not advertised to EBGP peer
)
Advertised to update-groups:
5
Refresh Epoch 3
54 50 60
155.1.108.10 from 155.1.108.10 (31.3.0.1)
Origin IGP, localpref 100, valid, external, best Community: no-export
rx pathid: 0, tx pathid: 0x0

R5#aggregate-address 112.0.0.0 248.0.0.0 summary-only as-set
R5#show ip bgp 112.0.0.0 248.0.0.0
BGP routing table entry for 112.0.0.0/5, version 75 Paths: (1 available, best #1, table default,
not advertised to EBGP peer
)
Advertised to update-groups:
21 22
Refresh Epoch 1
{54,50,60}, (aggregated by 200 150.1.5.5)
0.0.0.0 from 0.0.0.0 (150.1.5.5)
Origin IGP, localpref 100, weight 32768, valid, aggregated, local, best Community: no-export
rx pathid: 0, tx pathid: 0x0


When you use the as-set parameter to the aggregate-address command, the
resulting prefix will inherit “additive” attributes of the specific prefixes. This includes
the AS_PATH attributes, condensed into AS_SET and the community attributes,
which are grouped together from all prefixes. We will explore community signaling in
further detail, but for now remember that any prefix bearing the community attribute
value of “no-export” is not advertised to the adjacent ASs.
In our scenario, we have R8 tagging just one prefix—112.0.0.0/8 with the
community value of “no-export”. However, when R5 aggregates all prefixes into one,
the summary prefix inherits the “no-export” community from one of the specific
routes. In effect, AS 200 speakers will not be able to advertise the summary prefix to
the neighbors.
The solution to this problem is the use of the attribute-map parameter to the
aggregate-address command. This parameter specifies the route-map that sets BGP
attributes for the newly generated prefix. You may set any configuration BGP value,
such as metric, origin, local-preference, and so on. However, in our case we are
interested in setting the community attribute value for the summary. The route-map
applies the set community none command and erases all communities for the new
prefix. Naturally, all routers are configured to propagate communities across AS 200.

R5#route-map ATTR_MAP
set community none
!
router bgp 200
aggregate-address 112.0.0.0 248.0.0.0 summary-only as-set attribute-map ATTR_MAP

R5#show ip bgp 112.0.0.0 248.0.0.0
BGP routing table entry for 112.0.0.0/5, version 76
Paths: (1 available, best #1, table default)
Advertised to update-groups:
20 21 22
Refresh Epoch 1
{54,50,60}, (aggregated by 200 150.1.5.5)
0.0.0.0 from 0.0.0.0 (150.1.5.5)
Origin IGP, localpref 100, weight 32768, valid, aggregated, local, best
rx pathid: 0, tx pathid: 0x0



BGP Aggregation - Advertise Map:
=======================

When using the as-set keyword with BGP aggregation, some of the specific prefix
attributes got mixed together in the new prefix. Specifically, you should watch out for
the resulting AS_SET and list of community attributes. In the previous task, you
learned how to modify some of the aggregated prefix attributes. However, you
cannot manipulate an important attribute such as AS_SET directly. Instead, you
may specify the specific prefixes that will be used to make up the attribute list for the
aggregate prefix. This is accomplished by using the advertise-map parameter to the
aggregate-address command. The route-map used as advertise-map should permit
specific prefixes to be used to compose the aggregate attributes, such as AS_SET.
You can use only access-list, prefix-list, or as-path access-lists to match the specific
prefixes. Information from the prefixes denied by the route-map is not used when
constructing the resulting summary-prefix. You may use this method to remove the
prefixes with unwanted BGP community attributes as well.


In our scenario, the AS_SET attribute for the summary route should be composed of
AS numbers 200, 254, and 300. However, by using the advertise-map parameter,
we filter out prefix originated in AS 300 and thus end up with AS_SET of {200,254}.
This allows AS 300 accepting back the summary prefix.


On R4 before map with just aggregate-address and as-set:
 *>  222.22.0.0/22    0.0.0.0                       100  32768 {200,254,300} ?

R4, R6:
ip prefix-list AS300_PREFIX permit 222.22.3.0/24
!
route-map ADVERTISE_MAP deny 10
match ip address prefix-list AS300_PREFIX
!
route-map ADVERTISE_MAP permit 100
!
router bgp 100
aggregate-address 222.22.0.0 255.255.252.0 summary-only as-set advertise-map ADVERTISE_MAP

After:
fa
*>  222.22.0.0/22    0.0.0.0                       100  32768 {200,254} ?


Saturday, 19 December 2015

NAT

ip nat outside source list:   

translates the source of the IP packets that are traveling outside to inside
translates the destination of the IP packets that are traveling inside to outside

ip nat inside source list:

translates the source of IP packets that are traveling inside to outside
translates the destination of the IP packets that are traveling outside to inside

Quite many people don’t pay attention to the difference in handling packets on interfaces configured for NAT inside and outside. Here is an example to demonstrate how NAT “domains” interact with routing. Consider three routers connected in the following manner:

Example:
=======
nat-inside-outside
For this scenario we have no routing configured. Let’s use static NAT to provide connectivity between R1 and R2. R2 would see R1 as a host on local connected segment with the IP address 155.1.23.1 and R1 would see R2 as a host on it’s local segment with the IP address 155.1.13.2. This goal could be achieved with the following configuration:
R3:
!
interface Serial 1/0.301 point-to-point
 ip address 155.1.13.3 255.255.255.0
 ip nat inside
 no ip route-cache
!
interface Serial 1/0.302 multipoint
 ip address 155.1.23.3 255.255.255.0
 frame-relay map ip 155.1.23.2 302
 ip nat outside
 no ip route-cache

!
! Static NAT: translations are effectively bi-directional
!
ip nat inside source static 155.1.13.1 155.1.23.1
ip nat outside source static 155.1.23.2 155.1.13.2

R2:
!
! Add a Frame-Relay mapping for the new IP (representing R1)
! so that R2 would know how to reach the address over multipoint FR interface
!
interface Serial 1/0.203 multipoint
 ip address 155.1.23.2 255.255.255.0
 frame-relay map ip 155.1.23.3 203
 frame-relay map ip 155.1.23.2 203
Let’s see how it’s working. Note that we disabled route-cache on both interfaces to intercept packets via CPU.
Rack1R3#debug ip nat detailed
IP NAT detailed debugging is on

Rack1R3#debug ip packet detail
IP packet debugging is on (detailed)

Rack1R2#ping 155.1.23.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 155.1.23.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
Hmm…it fails. Look at the debugging output on R3:
Rack1R3#
!
! Packet on NAT outside (o - for outside) hits the interface
!
NAT*: o: icmp (155.1.23.2, 16) -> (155.1.23.1, 16) [84]

!
! Source and destination for the packet rewritten according to NAT rules
!
NAT*: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [84]
NAT*: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [84]

!
! The packet is routed after translation (with new source and destination IPs). Note that routing decision
! and the actual forwarding take place only after translation rules were triggered by NAT tables
!
P: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0
!
! The response packet from R1 comes in - to destination 155.1.13.2 -  routed via RIB (to the same interface)
! But no NAT rules were triggered since the destination interface is the same as input interface!
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), routed via RIB
IP: s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), len 100, rcvd 3
    ICMP type=0, code=0
OK hold here for a second.. Now we recall that for inside NAT routing is tried first, and only then the packet is translated according to the NAT rules. This is how the NAT order of operations works on the inside. So now it’s clear: IOS first tries to route packet to 155.1.13.2 – which is the same interface as it came in.. therefore the inside->outside translation never occurs! To fix this, let’s add a static route on R3:
R3:
ip route 155.1.13.2 255.255.255.255 155.1.23.2
Verification:
Rack1R2#ping 155.1.23.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 155.1.23.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 12/33/52 ms

Rack1R3#
!
! Outside: translate & route
!
NAT*: o: icmp (155.1.23.2, 17) -> (155.1.23.1, 17) [89]
NAT*: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [89]
NAT*: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [89]

!
! Routing decision and forwarding
!
IP: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0
!
! Inside: Routing decision - the packet is routed using our fixup static route
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.302), routed via RIB

!
! NAT rule (i - for inside) is triggered by the packet
!
NAT: i: icmp (155.1.13.1, 17) -> (155.1.13.2, 17) [89]     

!
! Source and destination addresses rewritten in the "opposite" direction
!
NAT: s=155.1.13.1->155.1.23.1, d=155.1.13.2 [89]
NAT: s=155.1.23.1, d=155.1.13.2->155.1.23.2 [89]

!
! Packet is sent to R2 (with the new source and destination) - forwarding takes place
!
IP: s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), g=155.1.23.2, len 100, forward
    ICMP type=0, code=0
Nice. So now we know the difference for sure: packets on the NAT outside are first translated and then routed. On the inside interface routing decision kicks in first and only then translation rules get applied followed by forwarding. Before we finish with that, recall new 12.3T feature called NAT Virtual Interface. With this feature we can now configure any interface as “NAT enabled” an get rid of those “inside” and “outside” domains . All NAT traffic passed through new virtual interface called NVI, in symmetric manner. Let’s reconfigure out task using this new concepts.
R3:
interface Serial 1/0.301 point-to-point
 no ip nat inside
 ip nat enable
!
interface Serial 1/0.302 multipoint
 no ip nat outside
 ip nat enable

!
!  Remove old rules
!
no ip nat inside source static 155.1.13.1 155.1.23.1
no ip nat outside source static 155.1.23.2 155.1.13.2

!
! Add "domainless" rules
!
ip nat source static 155.1.13.1 155.1.23.1
ip nat source static 155.1.23.2 155.1.13.2

no ip route 155.1.13.2 255.255.255.255 155.1.23.2
Verification:
Rack1R2#ping 155.1.23.1                 

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 155.1.23.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 12/40/60 ms

Rack1R3#
!
! Routing decision it taken: packet classified for NAT, since destination is in NAT table
! Note that no actual forwarding occurs, just routing decision to send packet
!
IP: tableid=0, s=155.1.23.2 (Serial1/0.302), d=155.1.23.1 (Serial1/0.302), routed via RIB

!
! Packet translated according to NAT rules (note "i" for inside NAT)
!
NAT: i: icmp (155.1.23.2, 19) -> (155.1.23.1, 19) [95]
NAT: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [95]
NAT: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [95]

!
! Another routing decision, for translated packet - now actual forwarding occurs
!
IP: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0

!
! Response comes in, first routing decision - NAT table entry matched
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), routed via RIB

!
! Packet translated ("i" - inside NAT)
!
NAT: i: icmp (155.1.13.1, 19) -> (155.1.13.2, 19) [95]
NAT: s=155.1.13.1->155.1.23.1, d=155.1.13.2 [95]
NAT: s=155.1.23.1, d=155.1.13.2->155.1.23.2 [95]

!
! Another routing decision, for post-translated packet, followed by forwarding
!
IP: tableid=0, s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), routed via RIB
IP: s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), g=155.1.23.2, len 100, forward
    ICMP type=0, code=0
So what’s the difference with NVI? First, we see that now NAT behaves symmetrically. Next, we see that NAT translation tables are used to take a “routing decision” to send packet to virtual interface. Packet is translated there and then another routing decision takes place, followed by packet forwarding. So the difference from the old model is that now routing decision is taken twice: before and after translation. This allows to get rid of any static routes needed by “legacy” NAT, since lookup is performed after translation.
To summarize: Domain-based NAT uses different orders of operations for inside and outside domain. NVI based NAT is symmetrical and performs routing lookup twice: first to send packet to NVI, second to route packet using the post-translated addresses.

http://blog.ine.com/2008/02/15/the-inside-and-outside-of-nat/