Fortinet black logo

What's new

What's new

FortiADC 7.4.3 offers the following new features and enhancements:

Hardware

New models: 320F and 420F

FortiADC 7.4.3 introduces the new FortiADC 320F and 420F models. For more information, please refer to the latest FortiADC datasheet.

Server Load Balancing

Auto Populate Real Servers

Introduced in FortiADC version 7.2.3, the Auto Populate Real Servers functionality is now supported in FortiADC 7.4.3. This allows you to auto-populate real servers using the real server's FQDN. When the real server has more than one IP address for DNS server responses, the auto-populate feature allows FortiADC to automatically generate additional real servers with these IP addresses.

Scripting

New load balancing command

The new LB:set_real_server() command allows you to specify a real server from the configured pool directly. It can be called in the following events: HTTP_REQUEST, HTTP_DATA_REQUEST, BEFORE_AUTH, AUTH_RESULT, PERSISTENCE, and POST_PERSIST.

Example for events with manual routing selection:

when HTTP_REQUEST {
	debug("===>>============begin HTTP scripting============\n")
	-- routing to set
	sr = "test07"
	s = LB:get_current_routing()
	if (s == nil or s == "") then
	    debug("===>>set routing to be '%s'\n", sr)
		LB:routing(sr)
		s = sr
	end
	debug("===>>current routing: %s\n", s)

    -- Real Server name 
	rs = "rs05"
	ret = LB:set_real_server(rs)
	if ret then
		debug("LB:set_real_server(%s) Success.\n", rs);
	else 
        debug("LB:set_real_server(%s) Failed.\n", rs);
	end
	debug("===>>============end  HTTP scripting============\n")
}

Example for events without manual routing selection:

when PERSISTENCE {
	debug("===>>============begin scripting============\n")
       -- Real Server name 
	rs = "rs06"
	ret = LB:set_real_server(rs)
	if ret then
		debug("set_real_server(%s) Success.\n", rs);
	else 
        debug("set_real_server(%s) Failed.\n", rs);
	end
	debug("===>>============end scripting============\n")
}
New SSL command

The new SSL:disable() command allows you to disable SSL dynamically. This is useful when a virtual server supports both SSL and non-SSL services. Disabling SSL only takes effect before the SSL handshake starts. On the client side, the SSL will be disabled right after the TCP connection is established within the TCP_ACCEPTED event. On the server side, SSL will be disabled before a real server connection has established, including the following events: HTTP_REQUEST, BEFORE_AUTH, AUTH_RESULT, PERSISTENCE, POST_PERSIST, and SERVER_BEFORE_CONNECT.

--Client side must be TCP ACCEPTED 
when TCP_ACCEPTED {
    	debug("------> TCP accepted begin:\n");
	srcIP = IP:client_addr();
	srcPort = IP:client_port();
	debug("------> Client ip:port %s:%s\n", srcIP, srcPort);

	destIP = IP:local_addr();
	destPort = IP:local_port();
	debug("------> Local ip:port %s:%s\n", destIP, destPort);
	
	if tonumber(destPort) == 80 then
		ret = SSL:disable("clientside");
		if ret then
			debug("------> SSL disable clientside successfully.\n");
		else
			debug("------> SSL disable clientside failed.\n");
		end
	else
	    debug("------> SSL disable clientside skipped.\n");
	end

	debug("------> TCP accepted end.\n");
}
--Server side can be called within many events
when HTTP_REQUEST {
    debug("------> HTTP Request begin:\n");
	srcIP = IP:client_addr();
	srcPort = IP:client_port();
	debug("------> Client ip:port %s:%s\n", srcIP, srcPort);
	
	destIP = IP:local_addr();
	destPort = IP:local_port();
	debug("------> Local ip:port %s:%s\n", destIP, destPort);
	
	if tonumber(destPort) == 80 then
		ret = SSL:disable("serverside");
		if ret then
			debug("------> SSL disable serverside successfully.\n");
		else
			debug("------> SSL disable serverside failed.\n");
		end
	else
	    debug("------> SSL disable serverside skipped.\n");
	end

	debug("------> HTTP Request end.\n");
}
Enhanced TCP command

The TCP:sockopt() command has been enhanced to read the Client Address from the TCP socket option by adding the "type" option that can get the information. This is useful for passing the original client IP to the server side after the client IP has already gone through NAT.
Note: Currently only the GET operation is supported for "type".

when HTTP_REQUEST {
	debug("============begin scripting.\n")
	
	clientip = nil
	t = {}
	t["op"] = "get"
	-- Set the custom TCP option type
	t["type"] = 28
	ret = TCP:sockopt(t)
	if ret and (string.len(ret)>=4) then
		debug("------> TCP get sockopt(%d): (returned %d bytes) successfully.\n", t["type"], string.len(ret));
		print_byte_array(ret)
		clientip = binStrToIpAddress(ret)
		debug("clientip = %s\n", clientip)
	else
		debug("------> TCP get sockopt(%d) failed.\n", t["type"])
	end

	if clientip then
		res = HTTP:header_insert("X-Forwarded-For", clientip)
		if res then
			debug("------> Header inserted successfully.\n")
		else
			debug("------> Header failed to insert.\n")
		end
	end
	
	debug("============end scripting.\n")
}

function binStrToIpAddress(binStr)
    return  tostring(string.byte(binStr,1)) .. "." .. tostring(string.byte(binStr,2)) ..
        	"." .. tostring(string.byte(binStr,3)) .. "." .. tostring(string.byte(binStr,4))
end

function print_byte_array(s)
  for i=1, string.len(s) do
     debug("0x%x.", string.byte(s,i))
  end
  debug("\n")
end

Troubleshooting

Client URL support in CLI

New CLI commands have been added to support curl (Client URL) troubleshooting:

  • execute curl allows you to set the Client URL.

  • execute curl-option allows you to set the Client URL options listed in the following table.

    Option

    Description

    header

    Specify the curl header(s) or set as "auto". Multiple headers can be separated by three colons,":::".

    http-version

    Specify the HTTP version: 0.9, 1.0, 1.1, or 2. The default version is 1.1.

    interface

    Specify the interface or IP, or set as "auto".

    raw

    Enable this option to disable all internal HTTP decoding of content or transfer encodings to allow them to pass unaltered in its "raw" form.

    raw-data

    Specify the raw body data or set as "auto". The allowable content length is 1-8192 characters.

    reset

    Reset settings.

    timeout

    Specify the connection timeout in seconds. Range is 1-120 seconds, and the default is 10 seconds.

    view-settings

    View the current options of the curl.
64-bit SNMP MIB ifXTable support for higher speed interfaces

FortiADC 7.4.3 introduces the new SNMP MIB ifXTable with 64-bit counters to allow users to query 10 G statistics.

What's new

FortiADC 7.4.3 offers the following new features and enhancements:

Hardware

New models: 320F and 420F

FortiADC 7.4.3 introduces the new FortiADC 320F and 420F models. For more information, please refer to the latest FortiADC datasheet.

Server Load Balancing

Auto Populate Real Servers

Introduced in FortiADC version 7.2.3, the Auto Populate Real Servers functionality is now supported in FortiADC 7.4.3. This allows you to auto-populate real servers using the real server's FQDN. When the real server has more than one IP address for DNS server responses, the auto-populate feature allows FortiADC to automatically generate additional real servers with these IP addresses.

Scripting

New load balancing command

The new LB:set_real_server() command allows you to specify a real server from the configured pool directly. It can be called in the following events: HTTP_REQUEST, HTTP_DATA_REQUEST, BEFORE_AUTH, AUTH_RESULT, PERSISTENCE, and POST_PERSIST.

Example for events with manual routing selection:

when HTTP_REQUEST {
	debug("===>>============begin HTTP scripting============\n")
	-- routing to set
	sr = "test07"
	s = LB:get_current_routing()
	if (s == nil or s == "") then
	    debug("===>>set routing to be '%s'\n", sr)
		LB:routing(sr)
		s = sr
	end
	debug("===>>current routing: %s\n", s)

    -- Real Server name 
	rs = "rs05"
	ret = LB:set_real_server(rs)
	if ret then
		debug("LB:set_real_server(%s) Success.\n", rs);
	else 
        debug("LB:set_real_server(%s) Failed.\n", rs);
	end
	debug("===>>============end  HTTP scripting============\n")
}

Example for events without manual routing selection:

when PERSISTENCE {
	debug("===>>============begin scripting============\n")
       -- Real Server name 
	rs = "rs06"
	ret = LB:set_real_server(rs)
	if ret then
		debug("set_real_server(%s) Success.\n", rs);
	else 
        debug("set_real_server(%s) Failed.\n", rs);
	end
	debug("===>>============end scripting============\n")
}
New SSL command

The new SSL:disable() command allows you to disable SSL dynamically. This is useful when a virtual server supports both SSL and non-SSL services. Disabling SSL only takes effect before the SSL handshake starts. On the client side, the SSL will be disabled right after the TCP connection is established within the TCP_ACCEPTED event. On the server side, SSL will be disabled before a real server connection has established, including the following events: HTTP_REQUEST, BEFORE_AUTH, AUTH_RESULT, PERSISTENCE, POST_PERSIST, and SERVER_BEFORE_CONNECT.

--Client side must be TCP ACCEPTED 
when TCP_ACCEPTED {
    	debug("------> TCP accepted begin:\n");
	srcIP = IP:client_addr();
	srcPort = IP:client_port();
	debug("------> Client ip:port %s:%s\n", srcIP, srcPort);

	destIP = IP:local_addr();
	destPort = IP:local_port();
	debug("------> Local ip:port %s:%s\n", destIP, destPort);
	
	if tonumber(destPort) == 80 then
		ret = SSL:disable("clientside");
		if ret then
			debug("------> SSL disable clientside successfully.\n");
		else
			debug("------> SSL disable clientside failed.\n");
		end
	else
	    debug("------> SSL disable clientside skipped.\n");
	end

	debug("------> TCP accepted end.\n");
}
--Server side can be called within many events
when HTTP_REQUEST {
    debug("------> HTTP Request begin:\n");
	srcIP = IP:client_addr();
	srcPort = IP:client_port();
	debug("------> Client ip:port %s:%s\n", srcIP, srcPort);
	
	destIP = IP:local_addr();
	destPort = IP:local_port();
	debug("------> Local ip:port %s:%s\n", destIP, destPort);
	
	if tonumber(destPort) == 80 then
		ret = SSL:disable("serverside");
		if ret then
			debug("------> SSL disable serverside successfully.\n");
		else
			debug("------> SSL disable serverside failed.\n");
		end
	else
	    debug("------> SSL disable serverside skipped.\n");
	end

	debug("------> HTTP Request end.\n");
}
Enhanced TCP command

The TCP:sockopt() command has been enhanced to read the Client Address from the TCP socket option by adding the "type" option that can get the information. This is useful for passing the original client IP to the server side after the client IP has already gone through NAT.
Note: Currently only the GET operation is supported for "type".

when HTTP_REQUEST {
	debug("============begin scripting.\n")
	
	clientip = nil
	t = {}
	t["op"] = "get"
	-- Set the custom TCP option type
	t["type"] = 28
	ret = TCP:sockopt(t)
	if ret and (string.len(ret)>=4) then
		debug("------> TCP get sockopt(%d): (returned %d bytes) successfully.\n", t["type"], string.len(ret));
		print_byte_array(ret)
		clientip = binStrToIpAddress(ret)
		debug("clientip = %s\n", clientip)
	else
		debug("------> TCP get sockopt(%d) failed.\n", t["type"])
	end

	if clientip then
		res = HTTP:header_insert("X-Forwarded-For", clientip)
		if res then
			debug("------> Header inserted successfully.\n")
		else
			debug("------> Header failed to insert.\n")
		end
	end
	
	debug("============end scripting.\n")
}

function binStrToIpAddress(binStr)
    return  tostring(string.byte(binStr,1)) .. "." .. tostring(string.byte(binStr,2)) ..
        	"." .. tostring(string.byte(binStr,3)) .. "." .. tostring(string.byte(binStr,4))
end

function print_byte_array(s)
  for i=1, string.len(s) do
     debug("0x%x.", string.byte(s,i))
  end
  debug("\n")
end

Troubleshooting

Client URL support in CLI

New CLI commands have been added to support curl (Client URL) troubleshooting:

  • execute curl allows you to set the Client URL.

  • execute curl-option allows you to set the Client URL options listed in the following table.

    Option

    Description

    header

    Specify the curl header(s) or set as "auto". Multiple headers can be separated by three colons,":::".

    http-version

    Specify the HTTP version: 0.9, 1.0, 1.1, or 2. The default version is 1.1.

    interface

    Specify the interface or IP, or set as "auto".

    raw

    Enable this option to disable all internal HTTP decoding of content or transfer encodings to allow them to pass unaltered in its "raw" form.

    raw-data

    Specify the raw body data or set as "auto". The allowable content length is 1-8192 characters.

    reset

    Reset settings.

    timeout

    Specify the connection timeout in seconds. Range is 1-120 seconds, and the default is 10 seconds.

    view-settings

    View the current options of the curl.
64-bit SNMP MIB ifXTable support for higher speed interfaces

FortiADC 7.4.3 introduces the new SNMP MIB ifXTable with 64-bit counters to allow users to query 10 G statistics.