"Själv är bäste dräng" as we say in swedish, meaning that you had better do it yourself to get it properly done.
Once I started, I found that the primitives available are quite rich, and a lot of the work-arounds I had envisioned were not needed at all!
The NAT machinery is quite aware of that changing addresses around does strange things to the routing. It is also aware that address range problems require more than one routing instance.
In all the right places in the NAT rules, you can add statements qualifying what routing instance you want involved, and it works!
Here is an example, hand edited from a working configuration. The proper use of zones, policies etc is left out.
The internet connection is simulated using a 10.10.10.0/24 network that also hosts the addresses for the exposed services as well as company-specific hide addresses.
Company A resides in the default routing instance, using 192.168.0.0/24 as its network. Ordinary NAT, proxy-arp etc is used to communicate with the internet (omitted).
Company B is then attached, but they also use 192.168.0.0/24 as their network. To solve this problem, their interface is put into a routing instance of their own.
Shown below is the glue necessary to make this work. The example has one default hide NAT rule, one destination NAT rule, and a static NAT rule.
Enjoy
interfaces {
fe-0/0/0 {
unit 0 {
description "Common internet connection";
family inet {
address 10.10.10.2/24;
}
}
}
fe-0/0/1 {
unit 0 {
description "Customer A network";
family inet {
address 192.168.0.1/24;
}
}
}
fe-0/0/7 {
unit 0 {
description "Customer B network";
family inet {
address 192.168.0.1/24;
}
}
}
}
routing-options {
static {
route 0.0.0.0/0 next-hop 10.10.10.1;
}
}
security {
nat {
source {
pool cust-b-hide {
routing-instance {
CUST-B;
}
address {
/* Hide address for customer B */
10.10.10.250/32;
}
}
rule-set cust-b-hide {
from interface fe-0/0/7.0;
to interface fe-0/0/0.0;
rule hide {
match {
source-address 0.0.0.0/0;
}
then {
source-nat {
pool {
cust-b-hide;
}
}
}
}
}
}
destination {
pool cust-b-dest {
routing-instance {
CUST-B;
}
/* Internal address of customer B inbound service */
address 192.168.0.36/32;
}
rule-set cust-b-dest {
from interface fe-0/0/0.0;
rule cust-b-dest-1 {
match {
/* Public address of customer B inbound service */
destination-address 10.10.10.251/32;
}
then {
destination-nat pool cust-b-dest;
}
}
}
}
static {
rule-set cust-b {
from interface fe-0/0/0.0;
rule cust-b-static {
match {
/* Public address of customer B static NAT host */
destination-address 10.10.10.252/32;
}
then {
/* Private address of customer B static NAT host */
static-nat prefix 192.168.0.37/32 routing-instance CUST-B;
}
}
}
}
proxy-arp {
interface fe-0/0/0.0 {
address {
10.10.10.250/32 to 10.10.10.252/32;
}
}
}
}
}
routing-instances {
CUST-B {
instance-type virtual-router;
interface fe-0/0/7.0;
routing-options {
static {
route 0.0.0.0/0 next-table inet.0;
}
}
}
}