FortiADC Script Reference Guide 7.4.1
FortiADC Script Reference Guide 7.4.1
FortiADC 7.4.1
FORTINET DOCUMENT LIBRARY
https://docs.fortinet.com
FORTINET BLOG
https://blog.fortinet.com
FORTIGUARD LABS
https://www.fortiguard.com
FEEDBACK
Email: [email protected]
Change Log 8
Introduction 9
Definition of terms 10
Configuration overview 11
Script reference 12
Control structures 13
Operators 14
String Library 15
Multiple Scripting Usage 16
Dynamic scripting configuration change 17
Function 18
Events 20
WAF events 24
Predefined commands 25
Management commands 26
MGM:get_session_id() 26
MGM:rand_id() 26
MGM:set_event(t) 27
MGM:set_auto(t) 27
IP commands 29
IP:Client_addr() 29
IP:server_addr() 30
IP:local_addr() 30
IP:remote_addr() 31
IP:client_port() 31
IP:server_port() 31
IP:local_port() 32
IP:remote_port() 32
IP:client_ip_ver() 33
IP:server_ip_ver() 33
TCP commands 34
TCP:reject() 34
TCP:set_snat_ip(str) 35
TCP:clear_snat_ip() 35
TCP:sockopt(t) 36
TCP:after_timer_set() 38
TCP:after_timer_cancel() 39
TCP:after_timer_get() 40
TCP:close() 41
HTTP commands 43
HTTP:header_get_names() 44
HTTP:header_get_values(header_name) 45
HTTP:header_get_value(header_name) 45
Change Log
Introduction
FortiADC SLB supports Lua scripts to perform actions that are not currently supported by the built-in feature set. Scripts
enable you to use predefined script commands and variables to manipulate the HTTP request/response or select a
content route. The multi-script support feature enables you to use multiple scripts by setting their sequence of execution.
Definition of terms
Frontend, backend:
When visiting the virtual server service, the client will create a connection with FortiADC. On the connection, source IP
address is client address, and destination address is virtual server address. After FortiADC receives the request from the
client, FortiADC will load balance the request back to the real servers. This time, FortiADC will create a connection with
the real server; on this connection, source IP address is FortiADC’s out interface IP address, and destination address is
the real server address.
The connection between the client and virtual server is considered frontend.
The connection between FortiADC and real server is considered backend.
Configuration overview
You can use scripts to perform actions that are not currently supported by the built-in feature set. Scripts enable you to
use predefined script commands and variables to manipulate the HTTP request/response or select a content route, or
get SSL info.
You can type or paste the script content into the configuration page.
Before you begin:
l Create a script.
l You must have Read-Write permission for Server Load Balance settings.
After you have created a script configuration object, you can specify it in the virtual server configuration.
To create a script configuration object:
1. Go to Server Load Balance > Scripts.
2. Click Create New to display the configuration editor.
3. Complete the configuration as shown.
4. Save the configuration.
Settings Guidelines
Script reference
Control structures
Type Structure
::location1::
Operators
Type List
test=str:sub(2,5)
debug("return: %s \n", test)
log("record a log")
result: “bcde”
For a tutorial on scripting with the Lua string library, see http://lua-users.org/wiki/StringLibraryTutorial.
String Library
The FortiADC OS supports only the Lua string library. All other libraries are disabled. The string library includes the
following string-manipulation functions:
• String.byte(s, i)
• String.char(i1,i2…)
• String.dump(function)
• String.find(s, pattern)
• String.format
• String.gmatch
• String.gsub
• String.len
• String.lower
• String.match
• String.rep
• String.reverse
• String.sub
• String.upper
• String.starts_with
• String.end_with
• String.format
Like:
a=12
b=string.format(“%s, pi=%.4f”, a, 3.14);
• {s:byte(1,-1)}
Like:
str = “abc\1\2\0”
t={str:byte(1,-1)}
When changing an in-use script, FortiADC supports dynamic reloading of the new scripting configuration.
Function
FortiADC supports the basic commands. If the user want more functions, the user can implement functions to define
more with the basic commands.
Syntax
function function_name(parameter)
…
end
FortiADC supports two cookie commands: cookie_list() and cookie(t) with t as a table input
when HTTP_REQUEST {
ret=HTTP:cookie_list()
for k,v in pairs(ret) do
debug("-----cookie name %s, value %s-----\n", k,v);
end
GET attribute path of cookie "test", can be used to get other attributes too
case_flag = 0; -- or 1
ret = get_cookie_attribute(HTTP, "test", "path", case_flag);--return value is either boolean
false or its value if exists
debug("-----get cookie path return %s-----\n", ret);
You need to make sure the cookie was not first created by the GET command. Otherwise, by
design FortiADC shall use SET command to change its value or attributes.
In HTTP REQUEST, use $Path, $Domain, $Port, $Version; in HTTP RESPONSE, use Path, Domain, Port, Version, etc.
ret = insert_cookie(HTTP, "test", "abc.d; $Path=/; $Domain=www.example.com, ")--return value
is boolean
debug("-----insert cookie return %s-----\n", ret);
}
attrname can be path, domain, expires, secure, maxage, max-age, httponly, version, port.
case_flag: If you use zero, FortiADC looks for default attributes named Path, Domain, Expires, Secure, Max-Age,
HttpOnly, Version, Port. By setting this to 1, you can specify the case sensitive attribute name to look for in t["parameter"]
which could be PAth, DOmaIn, MAX-AGE, EXpires, secuRE, HTTPONLy, VerSion, Port, etc.
function get_cookie_attribute(HTTP, cookiename, attrname, case_flag)
local t={};
t["name"]=cookiename
t["parameter"]=attrname;
t["case_sensitive"] = case_flag;
t["action"]="get"
return HTTP:cookie(t)
end
function set_cookie_value(HTTP, cookiename, newvalue)
local t={};
t["name"]=cookiename
t["value"]=newvalue
t["parameter"]="value";
t["action"]="set"
return HTTP:cookie(t)
end
function remove_whole_cookie(HTTP, cookiename)
local t={};
t["name"]=cookiename
t["parameter"]="cookie";
t["action"]="remove"
return HTTP:cookie(t)
end
function insert_cookie(HTTP, cookiename, value)
local t={};
t["name"]=cookiename
t["value"]=value;
t["parameter"]="cookie";
t["action"]="insert"
return HTTP:cookie(t)
end
Events
HTTP_DATA_REQUEST Allows the user to manipulate http request data. V4.8 and later
HTTP_DATA_RESPONSE Alllows the user to manipulate http response V4.8 and later
data.
WAF events
Use the WAF events to insert an action before or after a WAF scan.
In FortiADC, the WAF has six stages for when modules can scan for attacks:
l WAF_SCAN_STAGE_REQ_HEADER
l WAF_SCAN_STAGE_REQ_BODY (streaming stage)
l WAF_SCAN_STAGE_REQ_WHOLE_BODY
l WAF_SCAN_STAGE_RES_HEADER
l WAF_SCAN_STAGE_RES_BODY (streaming stage)
l WAF_SCAN_STAGE_RES_WHOLE_BODY
The WAF event may be applied to specific WAF stages depending on their hook point.
WAF_REQUEST_ATTACK_ After all request stages when there are when WAF_RESPONSE_BEFORE_
DETECTED attacks detected (violation). SCAN {
If WAF function is not enabled on VS, debug("test WAF_RESPONSE_
then this will not be triggered. BEFORE_SCAN\n")
If WAF module does not detect any }
violations, then this will not be
triggered.
Predefined commands
Management commands
MGM:get_session_id()
Syntax
MGM:get_session_id();
Arguments
N/A
Example
when HTTP_REQUEST {
sid = MGM:get_session_id()
debug(“session id: %s\n”, sid)
}
MGM:rand_id()
Syntax
MGM:rand_id();
Arguments
N/A
Example
when HTTP_REQUEST {
rid = MGM:rand_id()
debug(“rand id is %s\n”, rid)
}
MGM:set_event(t)
Allows the user to disable/enable the rest of the events from executing by disabling this event.
Syntax
MGM:set_event(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t["event"]="req"; -- can be "req", "res", "data_req", "data_res", "ssl_client", "ssl_
server", "tcp_accept", "tcp_close", "ssl_renego_client", "ssl_renego_server", "server_
connected", "server_close", "server_before_connect", "vs_listener_bind", "auth_result",
"cookie_bake"
t["operation"]="disable"; -- can be "enable", and "disable"
MGM:set_event(t);
debug("disable rest of the HTTP_REQUEST events\n");
}
MGM:set_auto(t)
In the case of keep-alive, all events will be re-enabled automatically even if they are disabled in the previous
TRANSACTION using the HTTP:set_event(t) command. To disable this automatic re-enabling behavior, you can call
HTTP:set_auto(t).
Syntax
MGM:set_auto(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t["event"]="req";
t["operation"]="disable";
MGM:set_auto(t);
debug("disable automatic re-enabling of the HTTP_REQUEST events\n");
}
Note: Event can be "req", "res", "data_req", "data_res", "ssl_server", "ssl_renego_server", "server_connected", "server_
close", "server_before_connect." Operation can be "enable", and "disable."
FortiADC version: V5.0
Used in events: ALL
IP commands
IP commands contain functions to obtain IP layer related information such as obtaining the IP address and port of the
server and client:
IP:Client_addr() on page 29 — Returns the client IP address of a connection; for the frontend, it will return the source
address, while for the backend, it will return the destination address.
IP:server_addr() on page 30 — Returns the IP address of the server in the backend.
IP:local_addr() on page 30 — For the frontend, it returns the IP address of the virtual server that the client is connected
to. For the backend, it returns the incoming interface IP address of the return packet.
IP:remote_addr() on page 31 — Returns the IP address of the host on the far end of the connection.
IP:client_port() on page 31 — Returns the client port number.
IP:server_port() on page 31 — Returns the server port number. It is the real server port.
IP:local_port() on page 32 — Returns the local port number. In the frontend, the local port is the virtual server port. In the
backend, the local port is the port used to connect to the gateway.
IP:remote_port() on page 32 — Returns the remote port number. In the frontend, the remote port is the client port. In the
backend, remote port is the real server port.
IP:client_ip_ver() on page 33 — Returns the current client IP version number of the connection, either 4 (for IPv4) or 6
(for IPv6).
IP:server_ip_ver() on page 33 — Returns the current server IP version number of the connection, either 4 (for IPv4) or 6
(for IPv6).
IP:Client_addr()
Returns the client IP address of a connection; for the frontend, it will return the source address, while for the backend, it
will return the destination address.
Syntax
cip=IP:client_addr()
Arguments
N/A
Example
when SERVERSSL_HANDSHAKE {
cip=IP:client_addr()
lip=IP:local_addr()
sip=IP:server_addr()
rip=IP:remote_addr()
cp=IP:client_port()
lp=IP:local_port()
sp=IP:server_port()
rp=IP:remote_port()
sipv=IP:server_ip_ver();
cipv=IP:client_ip_ver();
debug("in server ssl with remote addr %s:%s client %s:%s, local %s:%s, server %s:%s, ip
version %s:%s\n", rip, rp, cip, cp, lip,lp, sip, sp, sipv, cipv)
}}
IP:server_addr()
Syntax
sip=IP:server_addr()
Arguments
N/A
Example
IP:local_addr()
For the frontend, it returns the IP address of the virtual server that the client is connected to. For the backend, it returns
the incoming interface IP address of the return packet.
Syntax
sip=IP:local_addr()
Arguments
N/A
Example
IP:remote_addr()
Returns the IP address of the host on the far end of the connection.
Syntax
sip=IP:remote_addr()
Arguments
N/A
Examples
IP:client_port()
Syntax
cp=IP:client_port()
Arguments
N/A
Example
IP:server_port()
Syntax
sp=IP:server_port()
Arguments
N/A
Example
IP:local_port()
Returns the local port number. In the frontend, the local port is the virtual server port. In the backend, the local port is the
port used to connect to the gateway.
Syntax
sp=IP:local_port()
Arguments
N/A
Example
IP:remote_port()
Returns the remote port number. In the frontend, the remote port is the client port. In the backend, remote port is the real
server port.
Syntax
rp=IP:remote_port()
Arguments
N/A
Example
IP:client_ip_ver()
Returns the current client IP version number of the connection, either 4 (for IPv4) or 6 (for IPv6).
Syntax
cv=IP:client_ip_ver ()
Arguments
N/A
Example
IP:server_ip_ver()
Returns the current server IP version number of the connection, either 4 (for IPv4) or 6 (for IPv6).
Syntax
cv=IP:server_ip_ver ()
Arguments
N/A
Example
TCP commands
TCP commands contains functions to obtain and manipulate information related to the TCP layer, such as sockopt:
TCP:reject() on page 34 — Allows the user to reject a TCP connection from a client.
TCP:set_snat_ip(str) on page 35 — Allows the user to set the backend TCP connection’s source address and port.
TCP:clear_snat_ip() on page 35 — Allows the user to clear any IP that was set using the set_snat_ip() command.
TCP:sockopt(t) on page 36 — Allows the user to customize the send buffer and receive buffer size. Can set or get
various socket/IP/TCP operations, such as buffer size, timeout, MSS, etc. This currently only supports snd_buf and rcv_
buf buffer sizes. For client-side events, this command applies to the client-side socket; for server-side events, it applies
to server-side socket.
TCP:after_timer_set() on page 38 — Allows the user to create and schedule a timer with a callback function and timeout
value. This allows you to create multiple timers each with a unique callback function name.
TCP:after_timer_cancel() on page 39 — Allows the user to cancel a scheduled timer. This function can only cancel a
timer before it is triggered if it is not periodic.
TCP:after_timer_get() on page 40 — Allows the user to get the information about the scheduled timers.
TCP:close() on page 41 — Allows the user to close the TCP connection immediately.
TCP:reject()
Syntax
TCP:reject();
Arguments
N/A
Example
when TCP_ACCEPTED {
--check if the st is true or false;
If st then
TCP:reject();
end
}
TCP:set_snat_ip(str)
Allows the user to set the backend TCP connection’s source address and port.
Syntax
TCP:set_snat_ip(str);
Note: To use the set_snat_ip() command, you must ensure the SOURCE ADDRESS flag is selected in the HTTP or
HTTPS profile type.
Arguments
Name Description
Example
when TCP_ACCEPTED{
addr_group = “172.24.172.60/24”
client_ip = IP:client_addr()
matched = cmp_addr(client_ip, addr_group)
if matched then
if TCP:set_snat_ip(“10.106.3.124”) then
debug(“set SNAT ip to 10.106.3.124\n”)
end
end
}
Note: The VS must have the client address enabled in the profile, as shown in the example below.
config load-balance profile
edit "http"
set type http
set client-address enable
next
end
TCP:clear_snat_ip()
Allows the user to clear any IP that was set using the set_snat_ip() command.
Syntax
TCP:clear_snat_ip();
Arguments
N/A
Example
when HTTP_REQUEST {
if TCP:clear_snat_ip() then
debug(“clear SNAT ip!\n”)
}
TCP:sockopt(t)
Allows the user to customize the send buffer and receive buffer size. Can set or get various socket/IP/TCP operations,
such as buffer size, timeout, MSS, etc. This currently only supports snd_buf and rcv_buf buffer sizes. For client-side
events, this command applies to the client-side socket; for server-side events, it applies to server-side socket.
Syntax
TCP:sockopt(t);
Arguments
Name Description
Example
when RULE_INIT {
debug(" ======== RULE_INIT ========\n");
-- access to https://notes.shichao.io/unp/ch7/ for more details.
tcp_message = {};
tcp_message[1]="snd_buf"; --int
tcp_message[2]="rcv_buf"; --int
setIntMsg = {};
setIntMsg[1]="snd_buf"; --int
setIntMsg[2]="rcv_buf"; --int
setIntValue = {};
setIntValue[1] = 111222;
setIntValue[2] = 111222;
}
when VS_LISTENER_BIND{
--when a VS tries to bind.
debug(" ======== VS_LISTENER_BIND ========\n");
for k,v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
debug(" ==== set ==== \n");
for k,v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k,v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}
when HTTP_RESPONSE {
debug(" ======== HTTP_RESPONSE ========\n");
t={}
t["size"] = 100;
HTTP:collect(t)
debug(" ==== set ==== \n");
for k,v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k,v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}
when HTTP_DATA_RESPONSE {
debug(" ======== HTTP_DATA_RESPONSE ========\n");
debug(" ==== set ==== \n");
for k,v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k,v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}
TCP:after_timer_set()
Allows the user to create and schedule a timer with a callback function and timeout value. This allows you to create
multiple timers each with a unique callback function name. Periodic timers will be executed periodically until the
associated session is closed or the after_timer is closed.
Returns Boolean true if successful, otherwise, returns Boolean false.
Syntax
Arguments
Name Description
timer_cb_name A string of the callback function name. This is also the unique identification of a
timer. This parameter is required.
periodic A Boolean to indicate whether this timer is periodic. This parameter is required.
Example
when TCP_ACCEPTED {
debug("[%s]------> TCP accepted begin:\n",ctime());
local_count = 10
cip = IP:client_addr();
debug("[%s]------> client IP %s\n", ctime(),cip);
cport = IP:client_port();
debug("[%s]------> client Port %s\n", ctime(),cport);
debug("[%s]------> local_count= %d\n", ctime(),local_count);
debug("[%s]------> After function called here.\n",ctime());
AFTER_TIMER_NAME = function ()
debug("[%s]=======> After function call begin:\n",ctime())
cport = IP:client_port();
debug("[%s]=======> client Port %s\n",ctime(),cport);
debug("[%s]=======> After function call end.\n",ctime())
end
When the client successfully creates a TCP connection, the script will be executed. The function will be executed every 5
seconds (5000 milliseconds) and print out the text.
FortiADC console debug output:
[Thu Jan 11 16:30:50 2024]------> TCP accepted begin:
[Thu Jan 11 16:30:50 2024]------> client IP 10.1.0.161
[Thu Jan 11 16:30:50 2024]------> client Port 37818
[Thu Jan 11 16:30:50 2024]------> local_count= 10
[Thu Jan 11 16:30:50 2024]------> After function called here.
[Thu Jan 11 16:30:55 2024]=======> After function call begin:
[Thu Jan 11 16:30:55 2024]=======> client Port 37818
[Thu Jan 11 16:30:55 2024]=======> After function call end.
[Thu Jan 11 16:31:00 2024]=======> After function call begin:
[Thu Jan 11 16:31:00 2024]=======> client Port 37818
[Thu Jan 11 16:31:00 2024]=======> After function call end.
TCP:after_timer_cancel()
Allows the user to cancel a scheduled timer. This function can only cancel a timer before it is triggered if it is not periodic.
Returns Boolean true if successful, otherwise, returns Boolean false.
Syntax
TCP:after_timer_cancel (timer_cb_name);
Arguments
Name Description
timer_cb_name A string to indicate the name of the timer to be canceled. This parameter is
required.
Example
when TCP_ACCEPTED {
AFTER_TIMER_NAME = function ()
debug("[%s]====>After function call begin:\n",ctime());
debug("[%s]====>After function call end.\n",ctime());
end
TCP:after_timer_set("AFTER_TIMER_NAME", 1000, true);
}
when HTTP_REQUEST{
debug("[%s]------> Events: HTTP_REQUEST begin:\n", ctime());
TCP:after_timer_cancel("AFTER_TIMER_NAME");
}
When the client successfully creates a TCP connection, the script will be executed. When the HTTP is requested, the
AFTER_TIMER_NAME will be stopped.
FortiADC console debug output:
[Thu Oct 5 13:37:51 2023]====>After function call begin:
[Thu Oct 5 13:37:51 2023]====>After function call end.
[Thu Oct 5 13:37:52 2023]====>After function call begin:
[Thu Oct 5 13:37:52 2023]====>After function call end.
[Thu Oct 5 13:37:53 2023]------> Events: HTTP_REQUEST begin:
TCP:after_timer_get()
Allows the user to get the information about the scheduled timers.
When successful, returns a string for one timer, a table of strings for multiple timers. For example, the returned string
“'AFTER_TIMER_NAME':5000:periodic” shows the timer name, expiration in milliseconds and if it is periodic.
Returns nil for all failures.
Syntax
TCP:after_timer_get ([timer_cb_name]);
Arguments
Name Description
Example
when TCP_ACCEPTED {
AFTER_TIMER_NAME = function ()
debug("[%s]====>After function call begin:\n",ctime());
debug("[%s]====>After function call end.\n",ctime());
end
When the client successfully creates a TCP connection, the script will be executed. This function gets the after_timer
information and prints it out on the first line.
FortiADC console debug output:
after_timer_get success: 'AFTER_TIMER_NAME':1000:periodic
[Thu Oct 5 12:36:34 2023]====>After function call begin:
[Thu Oct 5 12:36:34 2023]====>After function call end.
[Thu Oct 5 12:36:35 2023]====>After function call begin:
[Thu Oct 5 12:36:35 2023]====>After function call end.
TCP:close()
Allows the user to close the TCP connection immediately. Once an associated session is closed, all the after_timers will
be deleted.
Returns Boolean true if successful, otherwise, returns Boolean false.
Syntax
TCP:close();
Arguments
N/A
Example
when TCP_ACCEPTED {
AFTER_TIMER_NAME = function ()
debug("[%s]====>After function call begin:\n",ctime());
debug("[%s]====>After function call end.\n",ctime());
end
When the client successfully creates a TCP connection, the script will be executed. When the HTTP is requested, the
TCP connection will be closed.
Client side:
[root@Client1 ~]# curl http://10.1.0.15 -v
* Trying 10.1.0.15:80...
* Connected to 10.1.0.15 (10.1.0.15) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.1.0.15
> User-Agent: curl/8.0.1
> Accept: */*
>
* Empty reply from server
* Closing connection 0
curl: (52) Empty reply from server
HTTP commands
The HTTP scripting class includes basic functions for manipulating HTTP elements and other important functions:
HTTP:header_get_names() on page 44 — Returns a list of all the headers present in the request or response.
HTTP:header_get_values(header_name) on page 45 — Returns a list of value(s) of the HTTP header named <header_
name>, with a count for each value.
HTTP:header_get_value(header_name) on page 45 — Returns the value of the HTTP header named <header_name>.
HTTP:header_remove(header_name) on page 46 — Removes all headers named with the name <header_name>.
HTTP:header_remove2(header_name, countid) on page 47 — Header_get_values() returns a count ID for each item.
HTTP:header_insert(header_name, value) on page 47 — Inserts the header <header_name> with value <value> into
the end of the HTTP request or response.
HTTP:header_replace(header_name, value) on page 48 — Replaces the occurrence value of header <header_name>
with value <value>.
HTTP:header_replace2(header_name, value, countid) on page 48 — Header_get_values() returns a count ID for each
item.
HTTP:header_exists(header_name) on page 49 — Returns true when the header <header_name> exists and false
when it does not exist.
HTTP:header_count(header_name) on page 50 — Returns the integer counter of the header <header_name>.
HTTP:method_get() on page 50 — Returns the string of the HTTP request method.
HTTP:method_set(value) on page 50 — Sets the HTTP request method to the string <value>.
HTTP:path_get() on page 51 — Returns the string of the HTTP request path.
HTTP:path_set(value) on page 51 — Sets HTTP request path to the string <value>.
HTTP:uri_get() on page 52 — Returns the string of the HTTP request URI.
HTTP:uri_set(value) on page 52 — Sets the HTTP request URI to the string <value>.
HTTP:query_get() on page 53 — Returns the string of the HTTP request query.
HTTP:query_set(value) on page 53 — Sets the HTTP request query to the string <value>.
HTTP:redirect(“url”, …) on page 54 — Redirects an HTTP request or response to the specified URL.
HTTP:redirect_with_cookie(url, cookie) on page 54 — Redirects an HTTP request or response to the specified URL with
cookie.
HTTP:redirect_t(t) on page 55 — Redirects an HTTP request or response to the URL specified in the table.
HTTP:version_get() on page 56 — Returns the HTTP version of the request or response.
HTTP:version_set(value) on page 56 — Sets the HTTP request or response version to the string <value>.
HTTP:status_code_get() on page 57 — Returns the response status code output as string.
HTTP:status_code_set(value) on page 57 — Sets the HTTP response status code.
HTTP:code_get() on page 58 — Returns the response status code, output as integer.
HTTP:header_get_names()
Syntax
HTTP:header_get_names();
Arguments
N/A
Example
when HTTP_REQUEST {
--use header and value
headers = HTTP:header_get_names()
for k, v in pairs(headers) do
debug("The value of header %s is %s.\n", k, v)
end
--only use the header name
for name in pairs(headers) do
debug("The request/response includes header %s.\n",name)
end
}
HTTP:header_get_values(header_name)
Returns a list of value(s) of the HTTP header named <header_name>, with a count for each value. Note that the
command returns all the values in the headers as a list if there are multiple headers with the same name.
Syntax
HTTP:header_get_values(header_name);
Arguments
Name Description
Example
when HTTP_REQUEST {
cookies=HTTP:header_get_values("Cookie")
for k, cnt in pairs(cookies) do
debug("initially include cookie %s cnt %d\n", k, v)
end
}
HTTP:header_get_value(header_name)
Returns false if the HTTP header named <header_name> does not exist. The command operates on the value of the last
head if there are multiple headers with the same name.
Syntax
HTTP:header_get_value(header_name);
Arguments
Name Description
Example
when HTTP_REQUEST {
host = HTTP:header_get_value("Host");
debug("host is %s\n", host);
}
HTTP:header_remove(header_name)
Syntax
HTTP:header_remove(header_name);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:header_remove(“Cookie”);
}
HTTP:header_remove2(header_name, countid)
Header_get_values() returns a count ID for each item. This count ID can be used in both header_remove2() and
header_replace2() to remove and replace a certain header of a given name referenced by the count ID.
Syntax
HTTP:header_remove2(header_name, countid);
Arguments
Name Description
Example
when HTTP_RESPONSE {
cookies=HTTP:header_get_values("Set-Cookie")
for k, v in pairs(cookies) do
debug("include cookie %s cnt %d\n", k, v)
end
if HTTP:header_remove2("Set-Cookie", 1) then
debug("remove 1st cookie\n")
end
}
HTTP:header_insert(header_name, value)
Inserts the header <header_name> with value <value> into the end of the HTTP request or response.
Syntax
HTTP:header_insert(header_name, value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:header_insert(“Cookie”, “insert_cookie=server1”)
}
HTTP:header_replace(header_name, value)
Syntax
HTTP:header_replace(header_name, value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:header_replace(“Host”, “www.fortinet.com”)
}
Header_get_values() returns a count ID for each item. This count ID can be used in both header_remove2() and
header_replace2() to remove and replace a certain header of a given name referenced by the count ID.
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
cookies=HTTP:header_get_values("Cookie")
for k, v in pairs(cookies) do
debug("include cookie %s cnt %d\n", k, v)
end
if HTTP:header_replace2("Cookie", “new_value”, 1) then
debug("replace 1st cookie\n")
end
}
HTTP:header_exists(header_name)
Returns true when the header <header_name> exists and false when it does not exist.
Syntax
HTTP:header_exists(header_name);
Arguments
Name Description
Example
when HTTP_REQUEST {
if HTTP:header_exists(“Cookie”) then
…
end
}
HTTP:header_count(header_name)
Syntax
HTTP:header_count(header_name);
Arguments
Name Description
Example
when HTTP_REQUEST {
count = HTTP:header_count(“Cookie”);
}
HTTP:method_get()
Syntax
HTTP:method_get();
Arguments
N/A
Example
when HTTP_REQUEST {
method = HTTP:method_get();
}
HTTP:method_set(value)
Syntax
HTTP:method_set(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:method_set(“POST”)
}
HTTP:path_get()
Syntax
HTTP:path_get();
Arguments
N/A
Example
when HTTP_REQUEST {
path = HTTP:path_get();
}
HTTP:path_set(value)
Syntax
HTTP:path_set(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:path_set(“/other.html”);
}
HTTP:uri_get()
Syntax
HTTP:uri_get();
Arguments
N/A
Example
when HTTP_REQUEST {
uri = HTTP:uri_get();
}
HTTP:uri_set(value)
Syntax
HTTP:uri_set(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:uri_set(“/index.html?para=xxxx”);
}
HTTP:query_get()
Syntax
HTTP:query_get();
Arguments
N/A
Example
when HTTP_REQUEST {
query = HTTP:query_get();
}
HTTP:query_set(value)
Syntax
HTTP:query_set(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:query_set(“query1=value1”);
}
HTTP:redirect(“url”, …)
Syntax
HTTP:redirect(“url”, …);
Arguments
Name Description
Example
when HTTP_REQUEST {
Host = HTTP:header_get_value("host")
Path = HTTP:path_get()
HTTP:redirect("https://%s%s", Host, Path);
}
HTTP:redirect_with_cookie(url, cookie)
Syntax
HTTP:redirect_with_cookie(url, cookie);
Arguments
Name Description
Example
HTTP:redirect_with_cookie("www.example.com", "server=nginx")
HTTP:redirect_with_cookie("www.abc.com", "server=nginx")
HTTP:redirect_t(t)
Syntax
HTTP:redirect_t(t);
Arguments
Name Description
Example
when HTTP_RESPONSE{
a={} --initialize a table
a["code"]=303;
a["url"]="www.example.com"
a["cookie"]="test:server"
HTTP:redirect_t(a)
debug("redirected\n")
}
Note:
HTTP:version_get()
Syntax
HTTP:version_get();
Arguments
N/A
Example
when HTTP_REQUEST {
v = HTTP:version_get();
}
HTTP:version_set(value)
Syntax
HTTP:version_set(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:version_set(“HTTP2.0”);
}
HTTP:status_code_get()
Syntax
HTTP:status_code_get();
Arguments: N/A
Example
when HTTP_RESPONSE {
code = HTTP:status_code_get();
}
HTTP:status_code_set(value)
Syntax
HTTP:status_code_set(value);
Arguments
Name Description
Example
when HTTP_RESPONSE{
HTTP:status_code_set(“304”);
}
HTTP:code_get()
Syntax
HTTP:code_get();
Arguments
N/A
Example
when HTTP_REQUEST {
code = HTTP:code_get();
}
HTTP:code_set(integer)
Syntax
HTTP:code_set(integer);
Arguments
Name Description
Example
when HTTP_REQUEST {
HTTP:coe_set(503);
}
HTTP:reason_get()
Syntax
HTTP:reason_get();
Arguments
N/A
Example
when HTTP_RESPONSE {
reason = HTTP:reason_get();
}
HTTP:reason_set(value)
Syntax
HTTP:reason_set(value);
Arguments
Name Description
Example
when HTTP_RESPONSE {
HTTP:reason_set(“Not exist !”);
}
HTTP:client_addr()
Syntax
HTTP:client_addr();
Arguments
N/A
Example
when HTTP_REQUEST priority 100 {
cip=HTTP:client_addr()
}
HTTP:local_addr()
For HTTP_REQUEST, returns the IP address of the virtual server the client is connected to; for HTTP_RESPONSE,
returns the incoming interface IP address of the return packet.
Syntax
HTTP:local_addr();
Arguments
N/A
Example
when HTTP_REQUEST {
lip = HTTP:local_addr()
}
HTTP:server_addr()
Syntax
HTTP:server_addr();
Arguments
N/A
Example
when HTTP_RESPONSE {
sip = HTTP:server_addr()
}
HTTP:remote_addr()
Returns the IP address of the host on the far end of the connection
Syntax
HTTP:remote_addr();
Arguments
N/A
Example
when HTTP_REQUEST {
rip = HTTP:remote_addr()
}
HTTP:client_port()
Syntax
HTTP:client_port();
Arguments
N/A
Example
when HTTP_REQUEST {
string1=HTTP:client_port()
string2=HTTP:local_port()
string3=HTTP:remote_port()
debug("result_client_port: %s \n",string1)
debug("result_local_port: %s \n",string2)
debug("result_remote_port: %s \n",string3)
}
when HTTP_RESPONSE {
debug("SERVER_side: \n")
string4=HTTP:server_port()
debug("result_server_port: %s \n",string4)
string5=HTTP:client_port()
string6=HTTP:local_port()
string7=HTTP:remote_port()
debug("result_client_port: %s \n",string5)
debug("result_local_port: %s \n",string6)
debug("result_remote_port: %s \n",string7)
}
HTTP:local_port()
Syntax
HTTP:local_port();
Arguments
N/A
Example
when HTTP_REQUEST {
string1=HTTP:client_port()
string2=HTTP:local_port()
string3=HTTP:remote_port()
debug("result_client_port: %s \n",string1)
debug("result_local_port: %s \n",string2)
debug("result_remote_port: %s \n",string3)
}
HTTP:remote_port()
Syntax
HTTP:remote_port();
Arguments
N/A
Example
when HTTP_REQUEST {
string1=HTTP:client_port()
string2=HTTP:local_port()
string3=HTTP:remote_port()
debug("result_client_port: %s \n",string1)
debug("result_local_port: %s \n",string2)
debug("result_remote_port: %s \n",string3)
}
HTTP:server_port()
Syntax
HTTP:server_port();
Arguments
N/A
Example
when HTTP_RESPONSE {
debug("SERVER_side: \n")
string4=HTTP:server_port()
debug("result_server_port: %s \n",string4)
string5=HTTP:client_port()
string6=HTTP:local_port()
string7=HTTP:remote_port()
debug("result_client_port: %s \n",string5)
debug("result_local_port: %s \n",string6)
debug("result_remote_port: %s \n",string7)
}
HTTP:client_ip_ver()
Returns the client IP version number. This can be used to get IPv4 or IPv6 versions.
Syntax
HTTP:client_ip_ver();
Arguments
N/A
Example
when HTTP_REQUEST {
string=HTTP:client_ip_ver()
debug("\nresult: %s \n",string)
}
when HTTP_RESPONSE{
string=HTTP:client_ip_ver()
debug("\nresult: %s \n",string)
}
HTTP:server_ip_ver()
Returns the server IP version number. This can be used to get IPv4 or IPv6 versions.
Syntax
HTTP:server_ip_ver();
Arguments
N/A
Example
when HTTP_REQUEST {
string=HTTP:server_ip_ver()
debug("\nresult: %s \n",string)
}
HTTP:close()
Syntax
HTTP:close();
Arguments
N/A
Example
when HTTP_REQUEST {
Example1:
HTTP:close in script 1
HTTP:close in script 2
ps: it will send the close message to client correctly
Example2:
HTTP:close()
HTTP:redirect_with_cookie("www.example.com","server=nginx")
ps:the client get the redirect message, the close message is overwritten
HTTP:close() --close http connection using code 503
HTTP:respond(t)
Allows you to return a customized page and send out an HTTP response directly from FortiADC.
Syntax
HTTP:respond(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
tt={}
tt["code"] = 200;
tt["content"] = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type:
text/plain\r\n\r\nXXXXX Test Page XXXXXXX";
status = HTTP:respond(tt);
debug("HTTP_respond() status: %s\n", status);
}
HTTP:get_session_id()
FortiADC will assign each session a unique ID and allow the user to get this unique ID through this function.
With this unique ID, the user can use Lua scripts to capture request headers, store them into a global variable indexed by
this unique ID, and then index a global variable using this unique ID to extract its own request header information in the
HTTP request event.
Syntax
HTTP:get_session_id();
Arguments
N/A
Example
When RULE_INIT{
Env={}
}
when HTTP_REQUEST{
id=HTTP:get_session_id()
debug("session id %d\n", id);
env[id]=nil
req={}
req["url"]=HTTP:uri_get()
req["method"]=HTTP:method_get()
env[id]=req
}
when HTTP_RESPONSE{
id=1
request=env[id]
if req then
debug("session id %d and url %s\n", id,request["url"]);
debug("session id %d and method %s\n", id,request["method"]);
end
}
Output:
session id 1
session id 1 and url /index.html
session id 1 and method GET
HTTP:rand_id()
Syntax
HTTP:rand_id();
Arguments
N/A
Example
when HTTP_REQUEST {
id = HTTP:rand_id();
debug(“random id: %s\n”, id)
}
HTTP:set_event(t)
Syntax
HTTP:set_event(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t["event"] = "data_res";
t["operation"] = "disable";
HTTP:set_event(t);
}
Note:
The event can be "req", "res", "data_req", "data_res". And the operation can be "enable" and "disable". This command
will generate a log if the event or operation is wrong.
FortiADC version: V4.8
Used in events: HTTP_REQUEST / HTTP_RESPONSE
HTTP:set_auto()
Syntax
HTTP:set_auto(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t["event"] = "data_req";
t["operation"] = "enable";
HTTP:set_auto(t);
}
Note:
The event can be "req", "res", "data_req", "data_res". And the operation can be "enable" and "disable". This command
will generate a log if the event or operation is wrong.
FortiADC version: V4.8
Used in events:
HTTP_REQUEST/HTTP_RESPONSE/HTTP_DATA_REQUEST/HTTP_DATA_RESPONSE/BEFORE_AUTH/AUTH_
RESULT/COOKIE_BAKE
WAF_REQUEST_BEFORE_SCAN/WAF_RESPONSE_BEFORE_SCAN/WAF_REQUEST_ATTACK_
DETECTED/WAF_RESPONSE_ATTACK_DETECTED
HTTP:get_unique_transaction_id()
Returns a unique ID per transaction in history. Each ID is a string consisting of 32 hex digits, for example
"b0b9fec0b4b28306a2bf4f63eb97520e".
Syntax
HTTP:get_unique_session_id();
Arguments
N/A
Example
when HTTP_REQUEST {
uid=HTTP:get_unique_session_id()
debug("Unique session id %s\n", uid);
}
HTTP:get_unique_session_id()
Returns a unique ID per session in history. Each ID is a string consisting of 32 hex digits, for example
"b6e49ca3c937baaa47f2d111f593be8b".
Syntax
HTTP:get_unique_session_id();
Arguments
N/A
Example
when HTTP_REQUEST {
uid=HTTP:get_unique_session_id()
debug("Unique session id %s\n", uid);
}
HTTP:get_unique_transaction_id()
Returns a unique ID per transaction in history. Each ID is a string consisting of 32 hex digits, for example
"b0b9fec0b4b28306a2bf4f63eb97520e".
Syntax
HTTP:get_unique_transaction_id();
Arguments
N/A
Example
when HTTP_REQUEST {
tuid=HTTP:get_unique_transaction_id()
debug("Unique transaction id %s\n", tuid);
}
If the HTTP data exceeds the 1.25M buffer size limit, FortiADC will only collect up to
the 1.25M limit of data and forward the excess data directly.
HTTP:collect() on page 71 — Collects body data from the HTTP request or response. You may specify a specific amount
using the length argument.
HTTP:payload(size) on page 72 — Returns the size of the buffered content. The returned value is an integer.
HTTP:payload(content) on page 72 — Returns the buffered content in a string.
HTTP:payload(set) on page 73 — Inserts the specified data at the specified location.
HTTP:payload(find) on page 73 — Searches for a particular string or a regular expression on the buffered data.
HTTP:payload(remove) on page 74 — Removes a particular string or a regular expression from the buffered data.
HTTP:payload(replace) on page 75 — Replaces a particular string or regular expression with a new string.
HTTP:collect()
Collects body data from the HTTP request or response. You may specify a specific amount using the length argument.
Syntax
HTTP:collect(t);
Arguments
Name Description
Example
when HTTP_RESPONSE{
debug("Start\n")
t={}
t["size"]=10
HTTP:collect(t)
debug("Done\n")
}
when HTTP_DATA_RESPONSE{
table={}
table["operation"]="size"
ret=HTTP:payload(table)
debug("Size: %d \n",ret)
}
Note: The "size" refers to the httproxy block size, which is limited by the FortiADC HARD LIMIT.
FortiADC version: V4.8
Used in events: HTTP_REQUEST / HTTP_RESPONSE
HTTP:payload(size)
Returns the size of the buffered content. The returned value is an integer.
Syntax
HTTP:payload(t);
Arguments
Name Description
Example
when HTTP_DATA_RESPONSE{
t1={}
t1["operation"]="size"
sz=HTTP:payload(t1)
debug("----response data size: %d-----\n", sz)}
HTTP:payload(content)
Syntax
HTTP:payload(str);
Arguments
Name Description
Example
when HTTP_DATA_REQUEST {
t={};
t[“operation”]=”content”; --return the buffered content
t[“offset”]=12;
t[“size”]=20;
ct = HTTP:payload(t); --return value is a string containing the buffered content
}
Note: The “offset” and “size” fields are optional. If the “offset” field is missing, zero is assumed. If the “size” field is
missing, it will operate on the whole buffered data.
FortiADC version: V4.8
Used in events: HTTP_DATA_REQUEST / HTTP_DATA_RESPONSE
HTTP:payload(set)
Syntax
HTTP:payload(t);
Arguments
Name Description
Example
when HTTP_DATA_REQUEST {
t={};
t[“operation”]=”set” --replace the buffered content by new data
t[“offset”]=12;
t[“size”]=20;
t[“data”]= ”new data to insert”;
ret = HTTP:payload(t); --return value is boolean: false if fail, true if succeed
}
Note: The “offset” and “size” fields are optional. If the “offset” field is missing, zero is assumed. If the “size” field is
missing, it will operate on the whole buffered data.
FortiADC version: V4.8
Used in events: HTTP_DATA_REQUEST / HTTP_DATA_RESPONSE
HTTP:payload(find)
Syntax
HTTP:payload(t);
Arguments
Name Description
Example
when HTTP_DATA_REQUEST {
t={};
t[“operation”]=”find”
t[“data”]=”sth”; -- can be a regular expression, like (s.h)
t[“offset”]=12;
t[“size”]=20;
t[“scope”]=”first” -- the scope field can be either “first” or “all”
ct = HTTP:payload(t); --return value is a boolean false if operation fail or the number of
occurrences found;
}
Note: The “offset” and “size” fields are optional. If the “offset” field is missing, zero is assumed. If the “size” field is
missing, it will operate on the whole buffered data. The “scope” field can be either be “first” or “all”.
FortiADC version: V4.8
Used in events: HTTP_DATA_REQUEST / HTTP_DATA_RESPONSE
HTTP:payload(remove)
Syntax
HTTP:payload(t);
Arguments
Name Description
t A table which specifies the parameters: data to remove, offset, size, scope.
Example
when HTTP_DATA_REQUEST {
t={};
t[“operation”]=”remove”
t[“data”]=”sth”; -- can be a regular expression, like (s.h)
t[“offset”]=12;
t[“size”]=20;
t[“scope”]=”first” --"first" or “all”
ct = HTTP:payload(t); --return value is a boolean false if operation fail or the number of
occurrences removed
}
HTTP:payload(replace)
Syntax
HTTP:payload(t);
Arguments
Name Description
t A table which specifies the parameters: data to replace, new_data, offset, size,
scope.
Example
when HTTP_DATA_REQUEST {
t={};
t[“operation”]=”replace”
t[“data”]=”sth”; -- can be a regular expression, like (s.h)
t[“new_data”]=”sth new”; --“new_data” field is needed for the “replace” operation.
t[“offset”]=12;
t[“size”]=20;
t[“scope”]=”first” -- or “all”
ct = HTTP:payload(t); --return value is a boolean false if operation fail or the number of
occurrences replaced
}
Cookie commands
HTTP:cookie_list()
Syntax
HTTP:cookie_list();
Arguments
N/A
Example
when HTTP_REQUEST {
ret=HTTP:cookie_list()
for k,v in pairs(ret) do
debug("cookie name %s, value %s\n", k,v);
end
}
HTTP:cookie(t)
Allows you to get/set cookie value and cookie attribute, remove a whole cookie, get the whole cookie in HTTP_
RESPONSE, and insert a new cookie.
Syntax
HTTP:cookie(t);
t = {}
t[“name”] = “name”
t[“parameter”] = {can be value, cookie, path, domain, expires, secure, maxage, max-age, httponly, version, port,
attrname }
t[“value”] = value
t[“case_sensitive”] = {0 or 1}
t[“action”] = {can be get, set, remove, insert}
ret = HTTP:cookie(t) --return is true if succeed or false if failed
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t["name"]="test"
t["parameter"]="value";--value, cookie, path, domain, expires, secure, maxage, max-age,
httponly, version, port, attrname,
t["action"]="get"--get, set, remove, insert
ret = HTTP:cookie(t)
if ret then
debug("get cookie value succeed %s\n",ret);
else
debug("get cookie value failed\n");
end
}
Note:
l name: specify cookie name
l parameter: specify cookie value and attribute, including value, cookie, path, domain, expires, secure, maxage, max-
age, httponly, version, port
l action: can be get, set, remove, insert
FortiADC version: before V5.0
Used in events: HTTP_REQUEST / HTTP_RESPONSE
HTTP:cookie_crypto(t)
The provided function response_encrypt_cookie can be used to perform cookie encryption in HTTP_RESPONSE and
request_decrypt_cookie can be used to perform cookie decryption in HTTP_REQUEST.
Syntax
HTTP:cookie_crypto(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
--encrypt cookie "test" in HTTP REQUEST before forwarding to real servers
local t={};
t["name"]="cookiename"
t["action"]="encrypt" --encrypt, or decrypt
t["key"]="0123456789ABCDEF";
t["prefix"]="XXXX";
t["size"]=size-- 128, 192, or 256, the corresponding key length is 16, 24, and 32
if HTTP:cookie_crypto(t) then
debug("Encrypt cookie succeed\n");
else
debug("Encrypt cookie failed\n");
end
}
Note:
l name: specify cookie name
l action: can be encrypt, or decrypt
l size: can be 128, 192, or 256, the corresponding key length is 16, 24, and 32
FortiADC version: before V5.2
Used in events: HTTP_REQUEST / HTTP_RESPONSE
Authentication commands
AUTH:get_baked_cookie()
Syntax
AUTH:get_baked_cookie();
Arguments
N/A
Example
when COOKIE_BAKE {
cookie = AUTH:get_baked_cookie()
debug(“Get cookie: %s\r\n”, cookie)
}
Result:
Get cookie: Set-Cookie:
FortiADCauthSI=lfGnC2gsl7xsbAg4JFs94e4CJfFXaP3U5z6QHvo7n08cCoT5MdtQog2LmcizPo3aRiBHY/RThhocq
G+DdnvsCLFJh3nBUoLeuYjGK9lY5L4=|W86hXGg; expires=Tue 23 Oct 2018 04:19:45 GMT;
domain=10.1.0.99; path=/
AUTH:set_baked_cookie(cookie)
Syntax
AUTH:set_baked_cookie(cookie);
Arguments
Name Description
Example
when COOKIE_BAED {
cookie = AUTH:get_baked_cookie()
new_cookie = cookie..”; Mick-Test:123444444”
status = AUTH:set_baked_cookie(new_cookie)
debug(“Set baked cookie, status: %s\n”, status)
}
Result:
Set baked cookie, status: true
AUTH:on_off()
Syntax
AUTH:on_off();
Arguments
N/A
Example
when AUTH_RESULT {
on_off = AUTH:on_off()
succ = AUTH:success()
fm = AUTH:form_based()
user = AUTH:user()
pass = AUTH:pass()
userg = AUTH:usergroup()
realm = AUTH:realm()
host = AUTH:host()
debug(“authentication form based %s, on_off %s, success %s, the user %s, pass %s, realm %s,
the usergroup %s, host %s\n”, fm, on_off, succ, the user, pass, realm, the userg, host)
}
Result:
authentication form based true, on_off true, success true, the user test, pass test, realm
Form333333, the userg test, host 10.1.0.99
AUTH:success()
Syntax
AUTH:success();
Arguments
N/A
Example
AUTH:form_based()
Syntax
AUTH:form_based();
Arguments
N/A
Example
AUTH:user()
Syntax
AUTH:user();
Arguments
N/A
Example
AUTH:pass()
Syntax
AUTH:pass();
Arguments
N/A
Example
AUTH:usergroup()
Syntax
AUTH:usergroup();
Arguments
N/A
Example
AUTH:realm()
Syntax
AUTH:realm();
Arguments
N/A
Example
AUTH:host()
Syntax
AUTH:host();
Arguments
N/A
Example
AUTH:set_usergroup()
Sets a new user group that is configured in the current authentication policy. A new realm can also be set at the same
time. It returns true if successful, otherwise, false. A realm name and a user group name are needed as input
parameters.
The user group specified by the function must be in the authentication policy referenced by the VS. The result specified
by the new user group will override the authentication result of the original authentication policy.
Syntax
AUTH:set_usergroup(“RealmName”, "UserGroupName");
Arguments
Name Description
RealmName The name of the new realm to be set. (Lua string with maximum length of 63).
UserGroupName The name of the user group to be set. (Lua string with maximum length of 63,
must also comply with original definition of user group).
Example
when BEFORE_AUTH {
r = AUTH:set_usergroup(“Realm02”, "UserGroup02");
debug("set_usergroup successfully? %s\n", tostring(r));
}
SSL commands
SSL commands contain functions for obtaining SSL related information, such as obtaining certificates and SNI:
SSL:cipher() on page 87 — Returns the cipher in the handshake.
SSL:version() on page 88 — Returns the SSL version in the handshake.
SSL:alg_keysize() on page 88 — Returns the SSL encryption key size in the handshake.
SSL:client_cert() on page 89 — Returns the status of client-certificate-verify, whether or not it is enabled.
SSL:sni() on page 90 — Returns the SNI or false (if no SNI).
SSL:npn() on page 91 — Returns the next protocol negotiation string or false (if no NPN).
SSL:alpn() on page 91 — Allows you to get the SSL ALPN extension.
SSL:session(t) on page 92 — Allows you to get SSL session ID, reuse the session, or remove it from the cache.
SSL:cert(t) on page 92 — Allows you to get the certificate information between local or remote.
SSL:cert_der() on page 93 — Returns the DER certificate when the client enables verify certificate.
SSL:peer_cert(str) on page 94 — Returns the peer certificate.
SSL:cipher()
Syntax
SSL:cipher();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE{
debug("client_handshake\n")
ci=SSL:cipher();
debug("Cipher: %s \n",ci);
}
Result: (if client send https request with cipher ECDHE-RSA-DES-CBC3-SHA)
Cipher: ECDHE-RSA-DES-CBC3-SHA
SSL:version()
Syntax
SSL:version();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE{
debug("client handshake\n")
ver=SSL:version();
debug("SSL Version: %s \n",ver);
}
Result: (client send https request with various version)
client handshake
SSL Version: TLSv1
or
client handshake
SSL Version: TLSv1.1
or
client handshake
SSL Version: TLSv1.2
or
client handshake
SSL Version: SSLv3
SSL:alg_keysize()
Syntax
SSL:alg_keysize();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE{
debug("client handshake\n")
ci=SSL:cipher();
key=SSL:alg_keysize();
debug("Cipher: %s\n",ci)
debug("Alg key size: %s \n",key);
}
Result: (client send https request with various ciphers)
client handshake
Cipher: ECDHE-RSA-RC4-SHA
Alg key size: 128
or
client handshake
Cipher: ECDHE-RSA-DES-CBC3-SHA
Alg key size: 168
or
client handshake
Cipher: EDH-RSA-DES-CBC-SHA
Alg key size: 56
or
client handshake
Cipher: ECDHE-RSA-AES256-GCM-SHA384
Alg key size: 256
SSL:client_cert()
Syntax
SSL:client_cert();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE{
debug("client handshake\n")
cc=SSL:client_cert();
debug("Client cert: %s \n",cc);
}
Result:
SSL:sni()
Syntax
SSL:sni();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE {
debug("client handshake\n")
cc=SSL:sni();
debug("SNI: %s \n",cc);
}
Result:
Enable sni in client-ssl-profile
config load-balance client-ssl-profile
edit "csp"
SSL:npn()
Syntax
SSL:npn();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE {
npn = SSL:npn()
}
SSL:alpn()
Syntax
SSL:alpn();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE {
alpn = SSL:alpn()
}
SSL:session(t)
Allows you to get SSL session ID, reuse the session, or remove it from the cache.
Syntax
SSL:session(t);
Arguments
Name Description
Example
when CLIENTSSL_HANDSHAKE {
t={}
t[“operation”] = “get_id”; --can be “get_id” or “remove” or “reused”
sess_Id = SSL:session(t)
if sess_id then
id = to_HEX(sess_id)
debug(“client sess id %s\n”, id)
else
sess_id = “FALSE”
end
}
SSL:cert(t)
Syntax
SSL:cert(t);
Arguments
Name Description
Example
when CLIENTSSL_HANDSHAKE{
debug("client handshake\n")
t={}
t["direction"]="remote";
t["operation"]="index";
t["idx"]=0;
t["type"]="info";
cert=SSL:cert(t)
if cert then
debug("client has cert\n")
end
for k,v in pairs(cert) do
if k=="serial_number" or k=="digest" then
debug("cert info name %s, value in HEX %s\n", k, to_HEX(v));
else
debug("cert info name %s, value %s\n", k, v);
end
end
}
Note:
l direction: local and remote. In CLIENTSSL_HANDSHAKE, local means FortiADC's cert, remote means client's cert.
l operation: index, count, issuer
l type: info, der, (pem)
This command returns a table that contains all the information in the certificate.
In the return, it contains: key_algorithm, hash, serial_number, not Before, not After, signature_algorithm, version, digest,
issuer_name, subject_name, old_hash, pin-sha256, finger_print.
FortiADC version: V5.0
Used in events: CLIENTSSL_HANDSHAKE / SERVERSSL_HANDSHAKE / CLIENTSSL_RENEGOTIATE /
SERVERSSL_RENEGOTIATE
SSL:cert_der()
Returns the DER certificate when the client enables verify certificate.
Syntax
SSL:cert_der();
Arguments
N/A
Example
when CLIENTSSL_HANDSHAKE{
debug("client handshake\n")
cder=SSL:cert_der();
--debug("cder in HEX %s\n", to_HEX(cder));
if cder then
cder_hex=b64_enc_str(cder);
debug("whole cert : %s\n", cder_hex);
end
}
SSL:peer_cert(str)
Syntax
SSL:peer_cert(str);
Arguments
Name Description
Example
when CLIENTSSL_HANDSHAKE {
cder = SSL:peer_cert(“der”); --for remote leaf certificate, the input parameter can be
“info” or “der” or “pem”
if cder then
hash = sha1_hex_str(cder)
debug(“whole cert sha1 hash is: %s\n”, hash)
end
}
GEO IP commands
ip2country_name(ip)
Syntax
Ip2country_name(ip);
Arguments
Name Description
Example
when HTTP_REQUEST {
cip = IP:client_addr()
cnm = ip2country_name(cip)
debug(“cname %s\n”, cnm)
}
Ip2countryProv_name(ip)
Returns the GEO information (country name + possible province name) of an IP address.
Syntax
ip2countryProv_name(ip);
Arguments
Name Description
Example
when HTTP_REQUEST {
cip = IP:client_addr()
cnm = ip2countryProv_name(cip)
debug(“cname %s\n”, cnm)
}
Before you begin, ensure RAM caching configuration is selected in the HTTP or
HTTPs profile.
HTTP:exclude_check_disable()
Syntax
HTTP:exclude_check_disable();
Arguments
N/A
Example
when HTTP_REQUEST {
if HTTP:exclude_check_disable() then
debug("set HTTP:exclude_check_disable: true\n");
else
HTTP:cache_disable()
Syntax
HTTP: cache_disable();
Arguments
N/A
Example
when HTTP_REQUEST {
HTTP:cache_disable()
}
HTTP:dyn_check_disable()
Syntax
HTTP: dyn_check_disable();
Arguments
N/A
Example
when HTTP_REQUEST {
HTTP:dyn_check_disable
}
HTTP:dyn_invalid_check_disable()
Syntax
HTTP:dyn_invalid_check_disable();
Arguments
N/A
Example
when HTTP_REQUEST {
HTTP:dyn_invalid_check_disable()
}
HTTP:dyn_cache_enable(t)
Syntax
HTTP:dyn_cache_enable(t);
Arguments
Name Description
Examples
when HTTP_REQUEST {
t={}
t["id"] = 1;
t["age"] = 20; --in seconds
ret=HTTP:dyn_cache_enable(t)
}
HTTP: cache_user_key(t)
Replaces the default key (the URI) with any customized key.
Syntax
HTTP:cache_user_key(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
url = HTTP:uri_get()
new_url = url.."external";
t={};
t["uri"] = new_url
HTTP:cache_user_key(t)
}
HTTP:dyn_cache_invalid(t)
Syntax
HTTP:dyn_cache_invalid(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={}
t["id"] = 1 --between 1 and 1023
ret = HTTP:dyn_cache_invalid(t);
}
HTTP:cache_check(t)
Syntax
HTTP:cache_check(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={}
t["uri"] = "/3.htm";
ret=HTTP:cached_check(t)
if ret then
debug("cached with id %s\n", ret);
else
debug("not cached\n");
end
}
HTTP:cache_hits(t)
Syntax
HTTP:cache_hits(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={}
t["uri"] = "/3.htm";
ret=HTTP:cache_hits(t)
if ret then
debug("cache hit count %s\n", ret);
else
debug("not cached\n");
end
}
HTTP:res_caching()
Checks whether or not the response has been caching. If yes, then it checks whether it is regular cache or dynamic
cache.
Syntax
HTTP:res_caching();
Arguments
N/A
Example
when HTTP_RESPONSE {
id = HTTP:res_caching();
if id then
debug("HTTP:res_caching() response caching with id %s !!!!\n", id);
else
debug("HTTP:res_caching() response NOT caching\n");
end
}
HTTP:res_cached()
Check whether or not a response is from cache. If yes, then it checks whether it is regular cache or dynamic cache.
Syntax
HTTP:res_cached();
Arguments
N/A
Example
when HTTP_RESPONSE {
ret = HTTP:res_cached();
if ret then
debug("HTTP:res_cached() response from cache !!!!\n");
else
debug("HTTP:res_cached() response NOT from cache\n");
end
}
HTTP:caching_drop()
Syntax
HTTP:caching_drop();
Arguments
N/A
Example
when HTTP_RESPONSE {
ret=HTTP:caching_drop()
if ret then
debug("script dropping caching: True\n")
else
debug("script dropping caching: False\n");
end
}
PROXY commands
PROXY:set_auth_key(value) on page 105 — Customize the crypto key FortiADC used for encrypt/decrypt
authentication cookie name "FortiADCauthSI". This will increase your FortiADC's security so that others cannot forge
this authentication cookie.
PROXY:clear_auth_key(value) on page 105 — Clears the customized authentication key that was previously set to use
the default key instead.
PROXY:set_auth_key(value)
Customize the crypto key FortiADC used for encrypt/decrypt authentication cookie name "FortiADCauthSI". This will
increase your FortiADC's security so that others cannot forge this authentication cookie.
Syntax
PROXY:set_auth_key(value);
Arguments
Name Description
Example
when VS_LISTENER_BIND {
AUTH_KEY = “0123456789ABCDEF0123456789ABCDEF”
result = PROXY:set_auth_key(AUTH_KEY)
If result then
Debug(“set auth key succeed\n”)
end
}
PROXY:clear_auth_key(value)
Clears the customized authentication key that was previously set to use the default key instead.
Syntax
PROXY:clear_auth_key(value);
Arguments
Name Description
Example
when TCP_BIND {
result = PROXY:clear_auth_key()
}
LB commands
LB commands contain load balancing manipulating functions, with the most important function being LB:routing which
allows you to select the backend:
LB:routing(value) on page 107 — Routes the request to the content routing server.
LB:get_valid_routing() on page 108 — Returns a list of backend names configured on the current Virtual Server in the
form of a Lua table (number as key, string as value).
LB:get_current_routing() on page 108 — Returns the currently allocated backend for this request.
LB:method_assign_server() on page 109 — Returns the server through the current load balance method configured on
current the Virtual Server.
LB:routing(value)
Syntax
LB:routing(value);
Arguments
Name Description
Example
when HTTP_REQUEST {
LB:routing(“content_routing1”);
}
LB:get_valid_routing()
Returns a list of backend names configured on the current Virtual Server in the form of a Lua table (number as key, string
as value).
Since there must be at least one backend, the returned value cannot be nil or empty. In case of a single routing with zero
or one content routing configured, the pool name will be returned.
Syntax
LB:get_valid_routing();
Arguments
N/A
Example
when HTTP_REQUEST {
t=LB:get_valid_routing()
for k, v in pairs(t) do
debug("Key: %d Value: %s\n", k, v)
end
}
LB:get_current_routing()
Syntax
LB:get_current_routing();
Arguments
N/A
Example
when HTTP_REQUEST {
t=LB:get_current_routing()
if (s == nil or s == '') then
s = "No backend returned."
end
debug("current routing: %s\n", s).
}
LB:method_assign_server()
Returns the server through the current load balance method configured on current the Virtual Server.
The implementation will first check whether the backend is already set. If the backend is set, then it runs the load balance
algorithm to assign a server and returns the server name as a string. If the backend is not set, the function returns an
empty string, and then FortiADC will set the backend only if there is only one backend available. If there is no server
available in the corresponding pool or all the servers are down in the pool, an empty string will also be returned.
Syntax
LB:method_assign_server();
Arguments
N/A
Example
when HTTP_REQUEST {
s=LB:method_assign_server()
if (s == nil or s == '') then
s = "No Server returned."
end
debug("assign server: '%s'\n", s)
}
Note:
The result may be overwritten by functions in PERSISTENCE events, which happen after HTTP_REQUEST. For
example, this function returns server01. But the PERSISTENCE event specifies to use server02. The result from the
PERSISTENCE event (server02) will always supercede results from non-PERSISTENCE events (server01).
FortiADC version: V7.2
Used in events: HTTP_REQUEST / HTTP_DATA_REQUEST / AUTH_RESULT
Persistence commands
HTTP:persist(save_tbl)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
cip = HTTP:client_addr()
hash_str_cip = sha512_hex(cip)
debug("-----save_tbl-----\n")
t={}
t["operation"] = "save_tbl"
t["hash_value"] = hash_str_cip
t["srv_name"] = "pool1-2"
ret = HTTP:persist(t)
if ret then
debug("hash save table success\n");
else
debug("save table failed\n");
end
t={};
t["operation"] = "save_tbl";
t["hash_value"] = "246810";
t["srv_name"] = "pool1-3";
ret = HTTP: persist(t);
if ret then
debug("===server add success\n");
else
debug("===server add fail\n");
end
}
Output:
true: success, false: failed
Note:
Due to limitations in the stick table, it only supports 16 characters in the hash value. Otherwise, we will hash it to obtain
16 bytes as index.
FortiADC version: V5.4, V7.2 (extended function to HTTP_REQUEST events)
Used in events: PERSISTENCE / POST_PERSIST / HTTP_REQUEST
HTTP:persist(read_tbl)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
t={};
t["operation"] = "save_tbl";
t["hash_value"] = "246810";
t["srv_name"] = "pool1-3";
ret = HTTP: persist(t);
if ret then
debug("===server add success\n");
else
debug("===server add fail\n");
end
t={}
t["operation"] = "read_tbl"
t["hash_value"] = "246810"
ret_tbl = HTTP:persist(t)
if ret_tbl then
debug("246810-server: %s\n",ret_tbl)
else
debug("246810-server read fail\n")
end
}
Output:
Return server name of the entry, or false if no entry found
HTTP:persist(dump_tbl)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
t={};
t["operation"] = "save_tbl";
t["hash_value"] = "246810";
t["srv_name"] = "pool1-3";
ret = HTTP: persist(t);
if ret then
debug("===server add success\n");
else
debug("===server add fail\n");
end
t={}
t["operation"] = "dump_tbl"
t[“index”] = 1
t[“count”] = 15
ret_tbl = HTTP:persist(t)
if ret_tbl then
for hash, srv in pairs(ret_tbl) do
debug("tbl hash %s srv %s\n",hash,srv)
end
end
}
“index”:
“count”:
Output:
Return A table include hash and server name
HTTP:persist(get_valid_server)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
debug("-----get valid server-----\n")
t={}
t["operation"] = "get_valid_server"
ret = HTTP:persist(t)
if ret then
for srv,stat in pairs(ret) do
debug("server %s, status %s\n",srv,stat)
end
end
}
Output:
Return the table of usable real server and server state(enable, backup)
HTTP:persist(cal_server_from_hash)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
debug("-----cal_server_from_hash-----\n")
t={}
t["operation"] = "cal_server_from_hash"
t["hash_value"] = "246810"
ret = HTTP:persist(t)
if ret then
debug("hash 246810, server %s\n",ret)
end
}
Output:
Return the real server name according to the hash value using our algorithm or False if
failed
HTTP:lookup_tbl(t)
Use this hash value to lookup the stick table, and then persist the session.
Syntax
HTTP:lookup_tbl(t);
Arguments
Name Description
Example
when PERSISTENCE{
cip = HTTP:client_addr()
hash_str_cip = sha512_hex(cip)
t={}
t["operation"] = "save_tbl"
t["hash_value"] = hash_str_cip
t["srv_name"] = "pool1-3"
ret = HTTP:persist(t)
if ret then
debug("hash save table success\n");
else
debug("save table failed\n");
end
t={}
t["hash_value"]=hash_str_cip
ret = HTTP:lookup_tbl(t)
if ret then
debug("hash LOOKUP success\n")
else
debug("hash lookup failed\n")
end
}
Output:
Return True: lookup success, False, lookup failed and use the org. LB method
HTTP:persist(get_current_assigned_server)
Syntax
HTTP:persist(t);
Arguments
Name Description
Example
when PERSISTENCE{
cip = HTTP:client_addr()
hash_str_cip = sha512_hex(cip)
t={}
t["operation"] = "save_tbl"
t["hash_value"] = hash_str_cip
t["srv_name"] = "pool1-3"
ret = HTTP:persist(t)
if ret then
debug("hash save table success\n");
else
debug("save table failed\n");
end
t={}
t["hash_value"]=hash_str_cip
ret = HTTP:lookup_tbl(t)
if ret then
debug("hash LOOKUP success\n")
else
debug("hash lookup failed\n")
end
}
when POST_PERSIST{
debug("-----event POST_PERSIST-----\n")
PROXY:init_stick_tbl_timeout(int)
Syntax
PROXY:init_stick_tbl_timeout(init);
Arguments
Name Description
Example
when RULE_INIT{
env={}
PROXY:init_stick_tbl_timeout(500)
}
when PERSISTENCE{
cip = HTTP:client_addr()
hash_str_cip = sha512_hex(cip)
debug("-----save_tbl-----\n")
t={}
t["operation"] = "save_tbl"
t["hash_value"] = hash_str_cip
t["srv_name"] = "pool1-3"
ret = HTTP:persist(t)
if ret then
debug("hash save table success\n");
else
debug("save table failed\n");
end
}
Output:
Return True: success, False: failed
Global commands
Crc32(str) on page 120 — Returns the crc32 check value of the string, or 0 if it is an empty string.
Key_gen(str_pass, str_salt, iter_num, len_num) on page 120 — Creates an AES key to encrypt/decrypt data, either
generated by password or user defined.
Aes_enc(t) on page 121 — Encrypts the data using the previously-created AES key.
Aes_dec(t) on page 122 — Decrypts the data using the previously-created AES key.
EVP_Digest(alg, str) on page 123 — EVP_Digest for one-shot digest calculation.
HMAC(alg, str, key) on page 123 — HMAC message authentication code.
HMAC_verify(alg, data, key, verify) on page 124 — Checks if the signature is the same as the current digest.
G2F(alg, key) on page 125 — Returns a G2F random value.
Class_match(str, method, list) on page 125 — Matches the string against an element.
Class_search(list, method, str) on page 126 — Searches an element in the list against a string.
Cmp_addr() on page 127 — Matches one IP address against a group of IP addresses. It can automatically detect IPv4
and IPv6 and can be used to compare IPv4 addresses with IPv6 addresses.
url_enc(str) on page 128 — Converts the URL information into valid ASCII format.
url_dec(str) on page 128 — Converts the encoding-URL into the original URL.
url_parser(str) on page 129 — Parses a URL, returns a table containing host, port, path, query, fragment, the username,
password, etc., from the URL.
url_compare(url1, url2) on page 129 — Compares two URL strings, returns true if they are the same.
Rand() on page 130 — Generates a random number. Returns an integer number. After FortiADC reboots, the random
number will be different.
srand(str) on page 131 — Sets the random seed.
Rand_hex(int) on page 131 — Generates a random number in HEX. Returns a string, length is the <int>.
Rand_alphanum(int) on page 132 — Generates a random alphabet + number sequence. Returns a string, length is the
<int>.
Rand_seq(int) on page 132 — Generates a random number sequence. Returns a string, length is the <int>.
Time() on page 133 — Returns the current time as a number in seconds. This is the time since the Epoch was measured.
Ctime() on page 133 — Returns the current time as a string, for example, “Tue Jun 25 14:11:01 2019”.
gmtime() on page 134 — Returns the GMT time as a string, for example, “Thu 27 Jun 2019 18:27:42 GMT”.
Md5(str) on page 134 — Returns the MD5 calculated for the specified string.
Md5_hex(str) on page 135 — Returns the MD5 value in hex as a string.
Md5_str(str) on page 136 — Calculates the MD5 of a string input and stores the results in an intermediate variable, in
some cases you need a version to deal with it.
Md5_hex_str(str) on page 136 — Calculates the MD5 of a string input of a string input and outputs the results in HEX
format, in some cases you need a version to deal with it.
Sha1(str) on page 137 — Returns the SHA-1 calculated for the specified string.
Sha1_hex(str) on page 137 — Returns the SHA-1 calculated for the string in hex.
Sha1_str(str) on page 138 — Calculates the SHA-1 of a string input and stores the results in an intermediate variable, in
some cases you need a version to deal with it.
Sha1_hex_str(str) on page 138 — Calculates the SHA-1 of a string input and output the results in HEX format, in some
cases you need a version to deal with it.
Sha256(str) on page 139 — Calculates the SHA-256 of a string input and stores the result in an intermediate variable.
Sha256_hex(str) on page 139 — Calculates the SHA-256 of a string input and outputs the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha256_str(str) on page 140 — Calculates the SHA-256 of a string input and stores the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha256_hex_str(str) on page 140 — Calculates the SHA-256 of a string input and stores the result in an intermediate
variable. In some case you need a version to deal with it.
Sha384(str) on page 141 — Calculates the SHA-384 of a string input and stores the result in an intermediate variable.
Sha384_hex(str) on page 141 — Calculates the SHA-384 of a string input and outputs the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha384_str(str) on page 142 — Calculates the SHA-384 of a string input and stores the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha384_hex_str(str) on page 142 — Calculates the SHA-384 of a string input and stores the result in an intermediate
variable. In some case you need a version to deal with it.
Sha512(str) on page 143 — Calculates the SHA-512 of a string input and stores the result in an intermediate variable.
Sha512_hex(str) on page 143 — Calculates the SHA-512 of a string input and outputs the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha512_str(str) on page 144 — Calculates the SHA-512 of a string input and stores the result in an intermediate
variable. In some cases you need a version to deal with it.
Sha512_hex_str(str) on page 144 — Calculates the SHA-512 of a string input and stores the result in an intermediate
variable. In some case you need a version to deal with it.
B32_enc(str) on page 145 — Encodes a string input in Base32 and outputs the result in string format.
B32_enc_str(str) on page 145 — Encodes a string input in Base32 and outputs the result in string format. In some cases
you need a version to deal with it.
B32_dec(str) on page 146 — Decodes a Base32 encoded string input and outputs the result in string format.
B32_dec_str(str) on page 146 — Decodes a Base32 encoded string input and outputs the result in string format. In some
cases you need a version to deal with it.
B64_enc(str) on page 147 — Encodes a string input in Base64 and outputs the result in string format.
B64_dec(str) on page 147 — Decodes a Base64 encoded string input and outputs the result in string format.
Get_pid() on page 148 — Returns the PID value of the VS process.
Table_to_string(t) on page 148 — Returns the table in a string.
Htonl(int) on page 149 — Converts a 32 bit long integer from host byte order to network byte order.
Ntohs(int) on page 149 — Converts a 16 bit short integer from network byte order to host byte order.
Htons(int) on page 150 — Converts a 16 bit short integer from host byte order to network byte order.
Ntohl(int) on page 151 — When receiving long integers in HTTP response from the network, this command converts a 32
bit long integer from network byte order to host byte order.
To_HEX(str) on page 151 — Returns the HEX calculate of the string.
Debug(str) on page 152 — Prints the debug information when VS using scripting.
Log(str) on page 152 — Prints the scripting running information in log format. When using this command, you should
enable scripting log.
File_open(path, str) on page 153 — Opens a file, returns a file object.
File_get(file, size) on page 153 — Returns the file content.
File_close(file) on page 154 — Closes a file.
Crc32(str)
Syntax
crc32(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str = "any string for crc32 calculation"
crc = crc32(str);
debug("crc is %d\n", crc);
}
Creates an AES key to encrypt/decrypt data, either generated by password or user defined.
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
new_key = key_gen("pass", "salt", 32, 32); -- first parameter is the password string,
second the salt string, third the number of iterations, fourth the key length
debug("new key in hex is %s\n", to_HEX(new_key));
}
Aes_enc(t)
Syntax
Aes_enc(t);
Arguments
Name Description
t A table which specifies the message, key, and key size that was used to encrypt.
Example
when HTTP_REQUEST {
t={};
t["message"] = "MICK-TEST";
t["key"] = "aaaaaaaaaabbbbbb" --16bit
t["size"]= 128 -- 128, 192, or 256, the corresponding key length is 16, 24, and 32
enc = aes_enc(t)
Note:
l Message: a string which will be encrypted
l Key: a string to encrypt str
l Size: must be 128, 192, or 256, the corresponding key length is 16, 24, and 32
FortiADC version: V5.2
Used in events: ALL
Aes_dec(t)
Syntax
Aes_dec(t);
Arguments
Name Description
t A table which specifies the message, key, and key size that was used to decrypt.
Example
when HTTP_REQUEST {
t={};
t["message"] = "MICK-TEST";
t["key"] = "aaaaaaaaaabbbbbb"
t["size"]= 128 -- 128, 192, or 256, the corresponding key length is 16, 24, and 32
enc = aes_enc(t)
--aes decryption
a={};
a["message"] = enc;
a["key"] = "aaaaaaaaaabbbbbb"
a["size"]= 128;
dec = aes_dec(a);
debug("key length %s decrypted is %s\n",”128” ,dec);
}
Note:
l Message: a string which will be decrypted
l Key: a string to decrypt str
l Size: must be 128, 192, or 256, the corresponding key length is 16, 24, and 32
FortiADC version: V5.2
Used in events: ALL
EVP_Digest(alg, str)
Syntax
EVP_Digest(alg, str);
Arguments
Name Description
Example
when HTTP_REQUEST {
alg = "MD5"; -- or "SHA1", "SHA256", "SHA384", "SHA512"
data = "your data"
re = EVP_Digest(alg, data);
debug("the digest in hex is %s\n", to_HEX(re));
}
Note:
Alg: type of hashing algorithms to use, must be MD5, SHA1, SHA256, SHA384, SHA512
FortiADC version: V5.2
Used in events: ALL
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
alg = "MD5"; -- or "SHA1", "SHA256", "SHA384", "SHA512"
data = "your data"
key = "123456789ABCDEF0123456789ABCDEF\121"; -- or you can generate a key using key_gen
re = HMAC(alg, data, key);
debug("the HMAC in hex is %s\n", to_HEX(re));
}
Note:
Alg: type of hashing algorithms to use, must be MD5, SHA1, SHA256, SHA384, SHA512
FortiADC version: V5.2
Used in events: ALL
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
alg = "MD5"; -- or "SHA1", "SHA256", "SHA384", "SHA512"
data = "your data"
verify = "your result to compare"
key = "123456789ABCDEF0123456789ABCDEF\121"; -- or you can generate a key using key_gen
re = HMAC_verify(alg, data, key, verify);
if re then
debug("verified\n")
else
debug("not verified\n")
end
}
Note:
Alg: type of hashing algorithms to use, must be MD5, SHA1, SHA256, SHA384, SHA512
FortiADC version: V5.2
Used in events: ALL
G2F(alg, key)
Syntax
G2F(alg, key);
Arguments
Name Description
Example
when HTTP_REQUEST {
alg = "MD5"; -- or "SHA1", "SHA256", "SHA384", "SHA512"
key = "123456789ABCDEF0123456789ABCDEF\121"; -- or you can generate a key using key_gen
re = G2F(alg, key);
debug("the G2F value is %d\n", re);
}
Note:
Alg: type of hashing algorithms to use, must be MD5, SHA1, SHA256, SHA384, SHA512
FortiADC version: V5.2
Used in events: ALL
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
url_list = “”
url = HTTP:uri_get()
status, count, t = class_match(url, "starts_with", url_list); --or "ends_with", "equals",
"contains"
debug("status %s, count %s\n", status, count);
for k,v in pairs(t) do
debug("index %s, value %s\n", k,v);
end
}
Note:
Method: must be “starts_with”, “equals”, “contains”, “end_with”
This command return three parameters, first “status”: true or false means if match or not; second “count”: return the
number of times matches; third “t”: return matched index and matched value in the list.
FortiADC version: V5.2
Used in events: ALL
Syntax
Arguments
Name Description
Example
when HTTP_REQUEST {
status, count, t = class_search(url_list, "starts_with", url); --or "ends_with",
"equals", "contains"
for k,v in pairs(t) do
debug("index %s, value %s\n", k,v);
end
}
Note:
Method: , must be “starts_with”, “equals”, “contains”, “end_with”
FortiADC version: V5.2
Used in events: ALL
Cmp_addr()
Matches one IP address against a group of IP addresses. It can automatically detect IPv4 and IPv6 and can be used to
compare IPv4 addresses with IPv6 addresses.
Syntax
Cmp_addr(client_Ip, addr_group );
Arguments
Name Description
Client_ip For an IPv4 ip_addr/[mask], the mask can be a number between 0 and 32 or a
dotted format like 255.255.255.0
For an IPv6 ip_addr/[mask], the mask can be a number between 0 and 128.
Example
when RULE_INIT{
}
when HTTP_REQUEST{
client_ip = HTTP:client_addr()
matched = cmp_addr(client_ip, addr_group)
if matched then
debug("client ip found in address group\n");
else
debug("client ip not in address group\n");
end
}
url_enc(str)
Syntax
url_enc(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
url_list =https://abc.www.123.bbEEE.com/?5331=212&qe1=222
debug("Ori= %s \nencodeed= %s\n", url_list,url_enc(url_list));
}
url_dec(str)
Syntax
url_dec(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str = "https%3A%2F%2Ffanyv88.com%3A443%2Fhttp%2Fwww.example.com%3A890%2Furl%2Fpath%2Fdata%3Fname%3Dforest%23nose“
debug("String= %s\ndecoded= %s\n", str,url_dec(str));
}
url_parser(str)
Parses a URL, returns a table containing host, port, path, query, fragment, the username, password, etc., from the URL.
Syntax
url_parser(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
url_list="http://foo:[email protected]/very/long/path.html?p1=v1&p2=v2#more-details"
purl = url_parser(url_list);
debug("parsed url scheme %s host %s\n port %s path %s query %s\n fragment %s, the username
%s\n passowrd %s\n", purl["scheme"], purl["host"], purl["port"],purl["path"], purl["query"],
purl["fragment"], purl["username"], purl["password"]);
}
url_compare(url1, url2)
Compares two URL strings, returns true if they are the same.
Syntax
url_compare(url1, url2);
Arguments
Name Description
Example
when HTTP_REQUEST {
url_list={};
url_list[1]="http://10.10.10.10:80/"
url_list[2]="http://10.10.10.10/"
url_list[3]="https://5.5.5.5:443/"
url_list[4]="https://5.5.5.5/"
url_list[5]="http://[2001::1]:80"
url_list[6]="http://[2001::1]"
url_list[7]="https://[2001:99:1]:443"
url_list[8]="https://[2001:99:1]"
for i = 1,8,2 do
if url_compare(url_list[i],url_list[i+1]) then
debug("URL_List %d %d Match !\n",i,i+1);
else
debug("URL_List %d %d NOT Match !\n",i,i+1);
end
end
}
Rand()
Generates a random number. Returns an integer number. After FortiADC reboots, the random number will be different.
Syntax
rand();
Arguments
N/A
Example
when HTTP_REQUEST {
a = rand()
debug(“a = %d\n”, a)
}
srand(str)
Syntax
srand(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
srand(1111)
a = rand()
debug(“a = %d\n”, a)
}
Rand_hex(int)
Syntax
Rand_hex(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
b = rand_hex(15)
debug("-----rand_hex b = %s-----\n", b)
}
Result:
-----rand_hex b = 43474FB47A8A8C4-----
Rand_alphanum(int)
Generates a random alphabet + number sequence. Returns a string, length is the <int>.
Syntax
Random_alphanum(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
c = rand_alphanum(17)
debug("-----rand_alphanum c = %s-----\n", c)
}
Result:
-----rand_alphanum c = XTHQpb6ngabMqH7nx-----
Rand_seq(int)
Syntax
Rand_seq(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
d = rand_seq(18)
debug("-----rand_seq d = %s-----\n", d)
}
Result:
-----rand_seq = 329514876985314568-----
Time()
Returns the current time as a number in seconds. This is the time since the Epoch was measured.
Syntax
time();
Arguments
N/A
Example
when HTTP_REQUEST {
t = time()
debug(“-----time: t %s-----\n”, t)
}
Result:
-----time: t 1561424783-----
Ctime()
Returns the current time as a string, for example, “Tue Jun 25 14:11:01 2019”.
Syntax
ctime();
Arguments
N/A
Example
when HTTP_REQUEST {
ct = ctime()
debug(“-----ctime: ct %s-----\n”, ct)
}
Result:
-----ctime: ct Mon Jun 24 18:06:23 2019-----
gmtime()
Returns the GMT time as a string, for example, “Thu 27 Jun 2019 18:27:42 GMT”.
Syntax
gmtime();
Arguments
N/A
Example
when HTTP_REQUEST {
gt = gmtime()
debug(“-----gmtime: gt %s-----\n”, gt)
}
Result:
-----gmtime: gt Thu 27 Jun 2019 18:27:42 GMT -----
Md5(str)
Syntax
Md5(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
md5 = md5(str1)
str = “test string”
a=12
md = md5(“%s,123%d”,str,a)
}
Md5_hex(str)
Syntax
Md5_hex(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
str2 = md5_hex(str1)
}
Md5_str(str)
Calculates the MD5 of a string input and stores the results in an intermediate variable, in some cases you need a version
to deal with it.
Syntax
Md5_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
md5 = md5_str(input); --input can be a cert in DER format
}
Md5_hex_str(str)
Calculates the MD5 of a string input of a string input and outputs the results in HEX format, in some cases you need a
version to deal with it.
Syntax
Md5_hex_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
md = md5_hex_str(input); --input can be a cert in DER format
}
Sha1(str)
Syntax
Sha1(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha1(input)
}
Sha1_hex(str)
Syntax
Sha1_hex(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “123456789”
sha1 = sha1_hex(str1)
}
Sha1_str(str)
Calculates the SHA-1 of a string input and stores the results in an intermediate variable, in some cases you need a
version to deal with it.
Syntax
Sha1_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha1_str(input); --input can be a cert in DER format
}
Sha1_hex_str(str)
Calculates the SHA-1 of a string input and output the results in HEX format, in some cases you need a version to deal
with it.
Syntax
Sha1_hex_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha1_hex_str(input); -- input can be a cert in DER format
}
Sha256(str)
Calculates the SHA-256 of a string input and stores the result in an intermediate variable.
Syntax
Sha256(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
str2 = sha256(str1)
}
Sha256_hex(str)
Calculates the SHA-256 of a string input and outputs the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha256_hex(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
sha256 = sha256_hex(str)
}
Sha256_str(str)
Calculates the SHA-256 of a string input and stores the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha256_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha256_str(input); --input can be a cert in DER format
}
Sha256_hex_str(str)
Calculates the SHA-256 of a string input and stores the result in an intermediate variable. In some case you need a
version to deal with it.
Syntax
Sha256_hex_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha256_hex_str(input); --input can be a cert in DER format
}
Sha384(str)
Calculates the SHA-384 of a string input and stores the result in an intermediate variable.
Syntax
Sha384(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
str2 = sha384(str1)
}
Sha384_hex(str)
Calculates the SHA-384 of a string input and outputs the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha384_hex(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
sha384 = sha384_hex(str)
}
Sha384_str(str)
Calculates the SHA-384 of a string input and stores the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha384_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha384_str(input); --input can be a cert in DER format
}
Sha384_hex_str(str)
Calculates the SHA-384 of a string input and stores the result in an intermediate variable. In some case you need a
version to deal with it.
Syntax
Sha384_hex_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha384_hex_str(input); --input can be a cert in DER format
}
Sha512(str)
Calculates the SHA-512 of a string input and stores the result in an intermediate variable.
Syntax
Sha512(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
str2 = sha512(str1)
}
Sha512_hex(str)
Calculates the SHA-512 of a string input and outputs the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha512_hex(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str1 = “abc”
sha512 = sha512_hex(str)
}
Sha512_str(str)
Calculates the SHA-512 of a string input and stores the result in an intermediate variable. In some cases you need a
version to deal with it.
Syntax
Sha512_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha512_str(input); --input can be a cert in DER format
}
Sha512_hex_str(str)
Calculates the SHA-512 of a string input and stores the result in an intermediate variable. In some case you need a
version to deal with it.
Syntax
Sha512_hex_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = sha512_hex_str(input); --input can be a cert in DER format
}
B32_enc(str)
Encodes a string input in Base32 and outputs the result in string format.
Syntax
B32_enc(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str = “abc”
en = b32_enc(str)
}
B32_enc_str(str)
Encodes a string input in Base32 and outputs the result in string format. In some cases you need a version to deal with it.
Syntax
B32_enc_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = b32_enc_str(input); --input can be a cert in DER format
}
B32_dec(str)
Decodes a Base32 encoded string input and outputs the result in string format.
Syntax
B32_dec(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str = “abc”
dec = b32_dec(str)
}
B32_dec_str(str)
Decodes a Base32 encoded string input and outputs the result in string format. In some cases you need a version to deal
with it.
Syntax
B32_dec_str(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = b32_dec_str(input); --input can be a cert in DER format
}
B64_enc(str)
Encodes a string input in Base64 and outputs the result in string format.
Syntax
B64_enc(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = b64_enc(input);
--Input can be general format:
str=”test string”
a=12
en=b64_enc(“%s, 123 %d”, str, a);
}
B64_dec(str)
Decodes a Base64 encoded string input and outputs the result in string format.
Syntax
B64_dec(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
result = b64_dec(input);
str=”test string”
a=12
Get_pid()
Syntax
Get_pid();
Arguments
N/A
Example
when HTTP_REQUEST {
pid = get_pid();
debug(“VS PID is : %d\n”, pid)
}
Table_to_string(t)
Syntax
Table_to_string(t);
Arguments
Name Description
Example
when HTTP_REQUEST {
t={};
t[1]=97;
t[2]=98;
t[3]=99;
t[4]=1;
str = table_to_string(t);
debug(“str is %s\n”, str)
}
Result:
str is abc
Htonl(int)
Converts a 32 bit long integer from host byte order to network byte order.
Syntax
htonl(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
str="0x12345678"
test=htonl(str)
debug("return : %x \n", test)
}
Result:
return: 78563412
Ntohs(int)
Converts a 16 bit short integer from network byte order to host byte order.
Syntax
ntohs(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
str="0x12345678"
test=ntohs(str)
debug("return : %x \n", test)
}
Result:
Return: 7856
Htons(int)
Converts a 16 bit short integer from host byte order to network byte order.
Syntax
htons(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
str="0x12345678"
test=htons(str)
debug("return : %x \n", test)
}
Result
Return: 7856
Ntohl(int)
When receiving long integers in HTTP response from the network, this command converts a 32 bit long integer from
network byte order to host byte order.
Syntax
ntohl(int);
Arguments
Name Description
Example
when HTTP_REQUEST {
str="0x12345678"
test=ntohl(str)
debug("return : %x \n", test)
log("record a log: %x \n", test)
}
Result:
return: 78563412
To_HEX(str)
Syntax
To_HEX(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
str = “\0\123\3”
hex = to_HEX(str)
debug(“this str in hex is: %s\n”, hex)
}
Debug(str)
Syntax
debug(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
debug(“http request method is %s.\n”, HTTP:method_get())
}
Log(str)
Prints the scripting running information in log format. When using this command, you should enable scripting log.
Syntax
log(str);
Arguments
Name Description
Example
when HTTP_REQUEST {
log(“http request method is %s.\n”, HTTP:method_get())
File_open(path, str)
Syntax
File_open(path, str);
Arguments
Name Description
Example
when HTTP_REQUEST {
filepath = "/etc/resolv.conf";
fp = file_open(filepath,"r");
if not fp then
debug("file open failed\n");
end
repeat
line = file_gets(fp, 256);
if line then
debug("line %s", line);
end
until not line
file_close(fp);
}
File_get(file, size)
Syntax
File_get(file, size);
Arguments
Name Description
File_close(file)
Closes a file.
Syntax
File_close(file);
Arguments
Name Description
WAF commands
WAF commands contain functions for obtaining and manipulating WAF related result information:
WAF:enable() on page 155 — Enables the current session's WAF scan function.
WAF:disable() on page 156 — Disables the current session's WAF scan function.
WAF:status() on page 156 — Returns a status string to specify the current status of WAF detection. The status may be
"enable" or "disable".
WAF:action() on page 156 — Returns the current session's WAF action. This can only be called in an ATTACK_
DETECTED event.
WAF:override_action(string) on page 157 — Overrides the current stage's detected action to the specified.
WAF:violations() on page 158 — Returns a table that includes all the violations detected by the current WAF stage as
string values.
WAF:abandon_violation() on page 159 — Removes a violation by the specified signature ID. The signature ID should be
a valid integer that is already in violations, otherwise, you can list the violations by calling WAF:violations. If the signature
ID is not valid, then it will return "false", otherwise, it will return "true".
WAF:raise_violation(string) on page 159 — Raises a violation immediately. This function will send a log by the input
arguments. If the signature ID is already raised by the WAF then this command will override it.
WAF:abandon_all() on page 161 — Abandons all of the results detected by the WAF module, including all of the
violations, and resets the action to "pass".
WAF:block(integer) on page 162 — Blocks the current session's client IP. Specify the period of the block in seconds as
an integer (Range: 1-2147483647, default = 3600).
WAF:unblock() on page 162 — Unblocks the client IP of the current session if it is already blocked.
WAF:enable()
Syntax
WAF:enable();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
local s = WAF:status()
debug("test WAF_REQUEST_ATTACK_DETECTED, status %s\n", s)
WAF:enable()
}
WAF:disable()
Syntax
WAF:disable();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
local s = WAF:status()
debug("test WAF_REQUEST_ATTACK_DETECTED, status %s\n", s)
WAF:disable()
}
WAF:status()
Returns a status string to specify the current status of WAF detection. The status may be "enable" or "disable".
Syntax
WAF:status();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
local s = WAF:status()
debug("test WAF_REQUEST_ATTACK_DETECTED, status %s\n", s)
WAF:disable()
}
WAF:action()
Returns the current session's WAF action. This can only be called in an ATTACK_DETECTED event.
The return value is a string, which may include the following values:
l "pass"
l "deny"
l "block"
l "redirect"
l "captcha"
Syntax
WAF:action();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
local s = WAF:action()
debug("test WAF_REQUEST_ATTACK_DETECTED, action %s\n", s)
WAF:override_action("deny", 501);
}
WAF:override_action(string)
Syntax
WAF:override_action(string);
Arguments
Name Description
block Requires a second argument specifying the period of the block as an integer
(Range: 1-2147483647, default = 3600).
Note: If the period is not specified, then it will be defaulted to 3600.
redirect Requires a second argument specifying the redirect URL, and it should be a valid
string. The redirect URL must be specified, otherwise this function will fail.
The return value is a bool value; when the function fails, it will return false,
otherwise, it will return true.
Example
when WAF_REQUEST_ATTACK_DETECTED {
local s = WAF:action()
WAF:violations()
Returns a table that includes all the violations detected by the current WAF stage as string values.
The table fields include the following:
Name Description
information The information that the WAF module defined when the specific attack was
detected.
signature An integer ID that is defined by the WAF module for every different attack.
action The defined action is a violation, including the values "pass", "deny", "block",
"redirect", or "captcha".
l waf_http_protocol_const
l waf_heur_sqlxss_inject_detect
l waf_url_protect,waf_bot_detection
l waf_xml_check
l waf_json_check
l waf_web_scraping
l waf_cookie_security
l waf_csrf_protection
l waf_html_input_validation
l waf_brute_force,waf_data_leak_prevention
l waf_credential_stuffing
l waf_openapi_check
l waf_api_gateway
Syntax
WAF:violations();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
debug("test WAF_REQUEST_ATTACK_DETECTED\n")
local vl = WAF:violations();
for k, v in pairs(vl) do
debug("%d. Violation: signature %d, severity %s, information %s, action %s, sub-category %s,
owasp-top10 %s.\n", k, v["signature"], v["severity"], v["information"], v["action"], v["sub-
category"], v["owasp-top10"]);
}
WAF:abandon_violation()
Removes a violation by the specified signature ID. The signature ID should be a valid integer that is already in violations,
otherwise, you can list the violations by calling WAF:violations. If the signature ID is not valid, then it will return "false",
otherwise, it will return "true".
This command can only be called in the ATTACK_DETECTED event.
Syntax
WAF:abandon_violation();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
debug("test WAF_REQUEST_ATTACK_DETECTED\n")
local vl = WAF:violations();
for k, v in pairs(vl) do
debug("%d. Violation: signature %d.\n", k, v["signature"]);
WAF:abandon_violation(v["signature"]);
end
v = {};
v["signature-id"] = 100010000;
v["severity"] = "high";
v["information"] = "waf raise violation test";
v["action"] = "deny";
v["sub-category"] = "waf_url_protect";
v["owasp-top10"] = "test-owasp10";
WAF:raise_violation(v);
}
WAF:raise_violation(string)
Raises a violation immediately. This function will send a log by the input arguments. If the signature ID is already raised
by the WAF then this command will override it.
This function will prevent the WAF action from executing as specified. To override the WAF action, call WAF:override_
action(string).
Syntax
WAF:raise_violation(string);
Arguments
Name Description
severity Overrides the severity string that includes the values "low", "medium", and "high".
Note: If the value is not specified, then "low" will be used as the severity level for
the violation.
information The violation will show the information that the WAF module defined when the
specific attack was detected.
Note: If this is not specified, then it will show "N/A" as the violation's information.
signature The attack signature string ID that WAF detected. Users can specify this if the
signature ID already exists in the violation, which will override the related field of
the violation by this function.
Note: This argument must be specified.
action The violation will show the defined action, including the values "pass", "deny",
"block", "redirect", or "captcha".
Note: If this is not specified, then the violation's action will take "pass" as default.
block-period If the action is "block", then this argument must be specified. Otherwise, this will
be defaulted to 3600.
This argument should be an integer and range from 1-2147483647.
redirect-url If the action is "redirect", then this argument must be specified. Otherwise, the
"redirect" action will be ignored and will take a "deny" action instead.
l waf_http_protocol_const
l waf_heur_sqlxss_inject_detect
l waf_url_protect,waf_bot_detection
l waf_xml_check
Name Description
l waf_json_check
l waf_web_scraping
l waf_cookie_security
l waf_csrf_protection
l waf_html_input_validation
l waf_brute_force,waf_data_leak_prevention
l waf_credential_stuffing
l waf_openapi_check
l waf_api_gateway
Note: This argument is not required to be specified. But if this argument is not
specified or if the string is not a valid sub-category, then it will default to "waf_
web_attack_signature".
owasp-top10 The string will show the violation that is related to the OWASP TOP10 field name.
Note: If this argument is not specified, then it will default to "unknown".
Example
when WAF_REQUEST_ATTACK_DETECTED {
debug("test WAF_REQUEST_ATTACK_DETECTED\n")
local vl = WAF:violations();
for k, v in pairs(vl) do
debug("%d. Violation: signature %d.\n", k, v["signature"]);
WAF:abandon_violation(v["signature"]);
end
v = {};
v["signature-id"] = 100010000;
v["severity"] = "high";
v["information"] = "waf raise violation test";
v["action"] = "deny";
v["sub-category"] = "waf_url_protect";
v["owasp-top10"] = "test-owasp10";
WAF:raise_violation(v);
}
WAF:abandon_all()
Abandons all of the results detected by the WAF module, including all of the violations, and resets the action to "pass".
This command can only be called in the ATTACK_DETECTED event.
Syntax
WAF:abandon_all();
Arguments
N/A
Example
when WAF_REQUEST_ATTACK_DETECTED {
debug("test WAF_REQUEST_ATTACK_DETECTED\n")
WAF:abandon_all()
}
WAF:block(integer)
Blocks the current session's client IP. Specify the period of the block in seconds as an integer (Range: 1-2147483647,
default = 3600).
Syntax
WAF:block(integer);
Arguments
Name Description
Example
when WAF_REQUEST_ATTACK_DETECTED {
debug("test WAF_REQUEST_ATTACK_DETECTED\n")
WAF:block(3600)
}
WAF:unblock()
Syntax
WAF:unblock();
Argument
N/A
Example
when WAF_REQUEST_BEFORE_SCAN {
local s = WAF:status()
debug("test WAF_REQUEST_BEFORE_SCAN, status %s\n", s)
WAF:unblock()
}
As of V5.3.0, FortiADC has the following built-in scripts; the user can refer to these examples to finish their scripting as
needed.
IP_COMMANDS Used to get various types IP Address and port number between client and server
side.
SNAT_COMMANDS Allows you to overwrite client source address to a specific IP for certain clients,
also support IPv4toIPv6 or IPv6toIPv4 type.
Note: Make sure the flag SOURCE ADDRESS is selected in the HTTP or HTTPS
type of profile.
SOCKOPT_COMMAND_ Allows the user to customize the TCP_send buffer and TCP_receive buffer size.
USAGE
GEOIP_UTILITY Used to fetch the GEO information country and possible province name of an IP
address.
CONTENT_ROUTING_by_URI Routes to a pool member based on URI string matches. You should not use this
script as is. Instead, copy it and customize the URI string matches and pool
member names.
GENERAL_REDIRECT_DEMO Redirects requests to a URL with the user-defined code and cookie.
Note: Do NOT use this script "as is". Instead, copy and customize the code, URL,
and cookie.
HTTP_2_HTTPS_ Redirects requests to the HTTPS site. You can use this script without changes
REDIRECTION
REDIRECTION_by_STATUS_ Redirects requests based on the status code of server HTTP response (for
CODE example, a redirect to the mobile version of a site). Do NOT use this script "as is".
Instead, copy it and customize the condition in the server HTTP response status
code and the URL values.
REDIRECTION_by_USER_ Redirects requests based on User Agent (for example, a redirect to the mobile
AGENT version of a site). You should not use this script as is. Instead, copy it and
customize the User Agent and URL values
REWRITE_HOST_n_PATH Rewrites the host and path in the HTTP request, for example, if the site is
reorganized. You should not use this script as is. Instead, copy
HTTP_DATA_FETCH_SET_ Collects data in HTTP request body or HTTP response body. In HTTP_
DEMO REQUEST or HTTP_RESPONSE, you could collect specified size data with
“size” in collect().In HTTP_DATA_REQUEST or HTTP_DATA_RESPONSE. You
could print the data use “content”, calculate data length with “size”, and rewrite the
data with “set”.
Note: Do NOT use this script "as is". Instead, copy it and manipulate the collected
data.
HTTP_DATA_FIND_REMOVE_ Finds a specified string, removes a specified string, or replaces a specified string
REPLACE_DEMO to new content in HTTP data.
Note: Do NOT use this script "as is". Instead, copy it and manipulate the collected
data.
USE_REQUEST_HEADERS_ Stores a request header value in an event and uses it in other events. For
in_OTHER_EVENTS example, you can store a URL in a request event, and use it in a response event.
Note: Do NOT use this script "as is". Instead, copy it and customize the content
you want to store, use collect() in HTTP_REQUEST to trigger HTTP_DATA_
REQUEST,or use collect() in HTTP_ RESPONSE to trigger HTTP_DATA_
RESPONSE.
SSL_EVENTS_n_COMMANDS Demonstrate how to fetch the SSL certificate information and some of the SSL
connection parameters between server and client side.
AUTH_COOKIE_BAKE Allows you to retrieve the baked cookie and edit the cookie content.
CUSTOMIZE_AUTH_KEY Demonstrate how to customize the crypto key for authentication cookie.
COOKIE_COMMANDS Demonstrate the cookie command to get the whole cookie in a table and how to
remove/insert/set the cookie attribute.
COOKIE_COMMANDS_USAGE Demonstrate the sub-function to handle the cookie attribute "SameSite" and
others.
AES_DIGEST_SIGN_2F_ Demonstrate how to use AES to encryption/decryption data and some tools to
COMMANDS generate the digest.
CLASS_SEARCH_n_MATCH Demonstrates how to use the class_match and class_search utility function.
INSERT_RANDOM_ Inserts a 32-bit hex string into the HTTP header with a parameter “Message-ID”.
MESSAGE_ID_DEMO Note: You can use the script directly, without making any change.
UTILITY_FUNCTIONS_DEMO Demonstrates how to use the basic string operations and random
number/alphabet, time, MD5, SHA1, SHA2, BASE64, BASE32, table to string
conversion, network to host conversion utility function.
SPECIAL_CHARACTERS_ Shows how to use those "magic characters" which have special meanings when
HANDLING_DEMO used in a certain pattern. The magic characters are ( ) . % + - * ? [ ] ^ $
MULTIPLE_SCRIPT_ Uses demo_1 and demo_2 script to show how multiple scripts work. Demo_1 with
CONTROL_DEMO_1 priority 12 has a higher priority.
Note: You could enable or disable other events. Do NOT use this script "as is".
Instead, copy it and customize the operation.
MULTIPLE_SCRIPT_ Uses demo_1 and demo_2 script to show how multiple scripts work. Demo_2 with
CONTROL_DEMO_2 priority 24 has a lower priority.
Note: You could enable or disable other events. Do NOT use this script "as is".
Instead, copy it and customize the operation
Copyright© 2024 Fortinet, Inc. All rights reserved. Fortinet®, FortiGate®, FortiCare® and FortiGuard®, and certain other marks are registered trademarks of Fortinet, Inc., and other Fortinet names herein
may also be registered and/or common law trademarks of Fortinet. All other product or company names may be trademarks of their respective owners. Performance and other metrics contained herein were
attained in internal lab tests under ideal conditions, and actual performance and other results may vary. Network variables, different network environments and other conditions may affect performance
results. Nothing herein represents any binding commitment by Fortinet, and Fortinet disclaims all warranties, whether express or implied, except to the extent Fortinet enters a binding written contract,
signed by Fortinet’s General Counsel, with a purchaser that expressly warrants that the identified product will perform according to certain expressly-identified performance metrics and, in such event, only
the specific performance metrics expressly identified in such binding written contract shall be binding on Fortinet. For absolute clarity, any such warranty will be limited to performance in the same ideal
conditions as in Fortinet’s internal lab tests. Fortinet disclaims in full any covenants, representations, and guarantees pursuant hereto, whether express or implied. Fortinet reserves the right to change,
modify, transfer, or otherwise revise this publication without notice, and the most current version of the publication shall be applicable.