The solution is to use a VIP object to replace one subnet broadcast address with another.
An essential part of the configuration is to enable broadcast-enable on the ingress interface.
Example configuration:
config system interface edit "lan" set ip 10.254.0.1 255.255.0.0
set broadcast-forward enable
next edit "dmz" set ip 192.168.0.1 255.255.255.0 next end
config firewall vip edit "bcast-vip" set extip 10.254.255.255 set extintf "any" set mappedip "192.168.0.255" next end
config firewall policy edit 0 set srcintf "lan" set dstintf "dmz" set srcaddr "all" set dstaddr "bcast-vip" set action accept set schedule "always" set service "ALL" next end
Troubleshooting:
FGT # diagnose sniffer packet any icmp 4 interfaces=[any] filters=[icmp] 73.345732 lan in 10.254.3.215 -> 10.254.255.255: icmp: echo request 73.346057 dmz out 10.254.3.215 -> 192.168.0.255: icmp: echo request
FGT # diagnose debug flow trace start 99
FGT # diagnose debug enable
id=20085 trace_id=1 func=print_pkt_detail line=5870 msg="vd-root:0 received a packet(proto=1, 10.254.3.215:768->10.254.255.255:2048) tun_id=0.0.0.0 from lan. type=8, code=0, id=768, seq=1." id=20085 trace_id=1 func=init_ip_session_common line=6042 msg="allocate a new session-000042cc, tun_id=0.0.0.0" id=20085 trace_id=1 func=get_new_addr line=1232 msg="find DNAT: IP-192.168.0.255, port-0(fixed port)" id=20085 trace_id=1 func=fw_pre_route_handler line=181 msg="VIP-192.168.0.255:768, outdev-unknown" id=20085 trace_id=1 func=__ip_session_run_tuple line=3508 msg="DNAT 10.254.255.255:8->192.168.0.255:768" id=20085 trace_id=1 func=vf_ip_route_input_common line=2606 msg="find a route: flag=04000000 gw-192.168.0.255 via dmz" id=20085 trace_id=1 func=fw_forward_handler line=883 msg="Allowed by Policy-1:"
FGT # diagnose sys session list
session info: proto=1 proto_state=00 duration=40 expire=19 timeout=0 flags=00000000 socktype=0 sockport=0 av_idx=0 use=3 origin-shaper= reply-shaper= per_ip_shaper= class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255 state=may_dirty npu statistic(bytes/packets/allow_err): org=84/1/1 reply=0/0/0 tuples=2 tx speed(Bps/kbps): 2/0 rx speed(Bps/kbps): 0/0 orgin->sink: org pre->post, reply pre->post dev=28->7/7->28 gwy=192.168.0.255/0.0.0.0 hook=pre dir=org act=dnat 10.254.3.215:768->10.254.255.255:8(192.168.0.255:768) hook=post dir=reply act=snat 192.168.0.255:768->10.254.3.215:0(10.254.255.255:768) misc=0 policy_id=1 pol_uuid_idx=518 auth_info=0 chk_client_info=0 vd=0 serial=000042cc tos=ff/ff app_list=0 app=0 url_cat=0 rpdb_link_id=00000000 ngfwid=n/a npu_state=0x4000000 npu info: flag=0x00/0x00, offload=0/0, ips_offload=0/0, epid=0/0, ipid=0/0, vlan=0x0000/0x0000 vlifid=0/0, vtag_in=0x0000/0x0000 in_npu=0/0, out_npu=0/0, fwd_en=0/0, qid=0/0 no_ofld_reason: total session 1
Note: The broadcast-forward enable option is used to control direct broadcasts, not traffic destined for 255.255.255.255. Therefore, it is not possible to allow traffic to 255.255.255.255. For example, if the DMZ interface is configured with the subnet 192.168.0.0/24, the directed broadcast address would be 192.168.0.255.
Related article:
Technical Tip: How to configure FortiGate forward broadcast |