Key concepts and features
This section covers key concepts and features you can reference when implementing Lua scripting in FortiWeb:
Lua package compatibility
FortiWeb uses Lua version 5.4.
|
Package name |
Compatible details |
|---|---|
| global |
Supported, but: • Disable dofile() • Disable loadfile() • Modify print() to FortiWeb version, printing to debug log with level 1. ( |
| package |
Disabled |
| coroutine | Disabled |
| table | Supported |
| io | Disabled |
| os | Disabled |
| string | Supported |
| math | Supported |
|
utf8 |
Supported |
Definition of terms
Frontend
The connection established between the client and FortiWeb when accessing a virtual server service.
Backend
The connection between FortiWeb and the real server after FortiWeb receives and load-balances the client request.
Source IP address (frontend)
The client IP address on the frontend connection.
Destination address (frontend)
The virtual server IP address on the frontend connection.
Source IP address (backend)
The IP address of FortiWeb’s outgoing interface on the backend connection.
Destination address (backend)
The real server IP address on the backend connection.
Control structures
The following table lists the Lua control structures.
|
Type |
Structure |
|---|---|
|
if then else |
if condition1 then
...
elseif condition2 then
...
break
else
...
goto location1
end
::location1::
|
|
for |
The following iterates through all key-value pairs in table 't': for k, v in pairs(t) do ... end |
Operators
Operators are symbols used to perform specific mathematical or logical manipulations.
The Lua language includes the following categories of built-in operators:
For more details, see the Lua Reference Manual.
Arithmetic operators
The arithmetic operators listed below operate on real numbers. In the Example column, assume that variable A is 10 and variable B is 20.
|
Operator |
Description |
Example |
|---|---|---|
|
+ |
Adds two operands. |
A + B results in 30. |
|
- |
Subtracts the second operand from the first. |
A - B results in -10. |
|
* |
Multiplies both operands. |
A * B results in 200. |
|
/ |
Divides the first operand by the second operand |
B / A results in 2. |
|
// |
Floor division divides two operands and rounds the result down toward negative infinity, returning the largest integer less than or equal to the exact division result. |
B // A results in 2. |
|
% |
Modulo returns the remainder of an integer division where the quotient is rounded toward negative infinity (floor division). |
B % A results in 0. |
|
^ |
Raises the first operand to the power of the second. |
A^2 results in 100 |
|
- |
Unary minus acts as negation. |
-A results in -10 |
Bitwise operators
Bitwise operators convert its operands to integers, operate on all bits of those integers, and result in an integer.
In the Example column, assume we have two integer variables with binary representations:
a = 1100; // (12 in decimal)
b = 1010; // (10 in decimal)
|
Operator |
Description |
Example |
|---|---|---|
|
& |
Bitwise AND: compares each bit of the first operand with the corresponding bit of the second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the result bit is set to 0. |
c = a & b; // (8 in decimal) c = 1000; |
|
| |
Bitwise OR: compares each bit of the first operand to the corresponding bit of the second operand. If either of the bits is 1, the corresponding result bit is set to 1. Otherwise, the result bit is set to 0. |
c = a | b; // (14 in decimal) c = 1110; |
|
^ |
Bitwise exclusive OR (XOR): compares each bit of the first operand to the corresponding bit of the second operand. If the bits are different, the corresponding result bit is set to 1. Otherwise, the result bit is set to 0. |
c = a ^ b; // (6 in decimal) c = 0110; |
|
>> |
Bitwise Right Shift: shifts the bits of the given number to the right by the specified positions. When a number is right shifted, 0s are added to the left side of the number, and the rightmost bits are discarded. |
Using a variable "n" and a shift count "s", the left shift operation can be represented as: c = n >> s; a = 1100; (12 in decimal) If we right shift "a" by 2 positions, the resulting value is: c = a >> 2; // (3 in decimal) c = 11; |
|
<< |
Bitwise Left Shift: shifts the bits of the given number to the left by the specified positions. When a number is left shifted, 0s are added to the right side of the number. The leftmost bits are discarded. |
Using a variable "n" and a shift count "s", the left shift operation can be represented as: c = n << s; a = 1010; (10 in decimal) If we left shift "a" by 2 positions, the resulting value is: c = a << 2; // (40 in decimal) c = 101000; |
|
~ |
Unary bitwise NOT: used to perform bitwise negation on a single operand. It flips all the bits of the operand, changing each - bit to 1 and each 1 bit to 0. |
Using the variable "a": a = 1010; (10 in decimal) c = ~a c = 11111111111111111111111111110101; (-11 in decimal) Applying the unary bitwise NOT operator to "10" flips all the bits, resulting in the Lua integer "-11". |
Relational operators
Lua provides the Relational operators listed below. This type of operator always results in true or false.
In the Example column, assume variable A is 10 and variable B is 20.
|
Operator |
Description |
Example |
|---|---|---|
|
== |
Checks if the value of two operands are equal or not. If yes, then the condition is true. |
(A == B) is false. |
|
~= |
Checks if the value of two operands are equal or not. If the values are not equal, then the condition is true. |
(A ~= B) is true. |
|
> |
Checks if the value of the left operand is greater than the value of the right operand. If yes, then the condition is true. |
(A > B) is not false. |
|
< |
Checks if the value of the left operand is less than the value of the right operand. If yes, then the condition is true. |
(A < B) is true. |
|
>= |
Checks if the value of the left operand is greater than or equal to the value of the right operand. If yes, then the condition is true. |
(A >= B) is false. |
|
<= |
Checks if the value of the left operand is less than or equal to the value of the right operand. If yes, then the condition is true. |
(A <= B) is true. |
Logical operators
Lua provides the Logical operators listed below. This type of operator considers false and nil both as false, and anything else as true.
In the Example column, assume variable A is 0 and variable B is 10.
|
Operator |
Description |
Example |
|---|---|---|
|
and |
Performs a logical "and" comparison between two values. If both the operands are non-zero then the condition is true. The operator and returns its first argument if it is false; otherwise, it returns its second argument. |
(A and B) is false. |
|
or |
Performs a logical "or" comparison between two values. If any of the two operands is non-zero, then the condition is true. The operator or returns its first argument if it is not false; otherwise, it returns its second argument |
(A or B) is true. |
|
! |
Performs a logical "not" on a value. Used to reverse the logical state of its operand. If a condition is true, then the logical not operator will make it false. |
!(A and B) is true. |
Miscellaneous operators
Miscellaneous operators supported by Lua include concatenation and length.
| Operator | Description | Example |
|---|---|---|
| .. |
The string concatenation operator in Lua is denoted by two dots ('..'). If both operands are strings or numbers, then they are converted to a string, similarly to __concat. |
a = "Hello " b = "World" a..b returns "Hello World". |
|
# |
The length operator returns the length of a string or an array-like table. The length of a string is its number of bytes (that is, the usual meaning of string length when each character is one byte). The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero. |
a = "FortiWeb" t = {1, 2, 3, 4} #a returns 8 #t returns 4 |
Functions
FortiWeb supports basic lua commands. Additional capabilities can be implemented by creating custom functions using these commands.
Syntax
function function_name(parameter) … End
For example, this function extracts all IPs from XFF headers and returns IP array:
function extract_xff(xff)
local t = {}
local k, v, s
for k, v in ipairs(xff) do
for s in v:gmatch("([^,]+)") do
t[#t + 1] = s:gsub("%s+", "")
end
end
return t
end
when HTTP_REQUEST {
local ips = extract_xff(HTTP:header("X-Forwarded-For"))
local r, i, v
for i, v in ipairs(ips) do
r = ip.reputation(v) -- check ip, will return an array
if #r > 0 then -- Found IP in reputation database
debug("Found bad IP %s in XFF headers, reputation: <%s>, GEO country: <%s>, GEO country code: %s\n",
v, table.concat(r, ', '),
ip.geo(v) or "unknown", ip.geo_code(v) or "unknown")
HTTP:close() -- force close this HTTP connection
return -- Stop script and return
end
end
}
String library
The FortiWeb 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.ends_with
|
|
|
For a tutorial on scripting with the Lua string library, see http://lua-users.org/wiki/StringLibraryTutorial.
Special characters
When written in a string, these characters look like this (between double quotes): "~!@#$^&*()_+{}[].?"
Note: The back slash (\) and the percent (%) signs are handled in a unique way in log and debug scripts. To print out %, you must use %%; to print out \, you must use \\.
|
Character |
Name |
|---|---|
|
~ |
Tilde |
|
! |
Exclamation |
|
@ |
At sign |
|
# |
Number sign (hash) |
|
$ |
Dollar sign |
|
^ |
Caret |
|
& |
Ampersand |
|
* |
Asterisk |
|
( |
Left parenthesis |
|
) |
Right parenthesis |
|
_ |
Underscore |
|
+ |
Plus |
|
{ |
Left brace |
|
} |
Right brace |
|
[ |
Left bracket |
|
] |
Right bracket |
|
. |
Full stop |
|
? |
Question mark |
|
\ |
Backslash |
HTTP data body commands
HTTP data body commands support regular expressions, where special characters such as $ ^ ? * + . | ( ) [ ] { } \ " have special meanings. You must escape these characters to treat them as literal values.
To escape a special character, prefix it with two backslashes (\\).
For example, to use the literal caret (^) in an HTTP data body command, enter \^.
For grouping characters such as parentheses (), square brackets [], or braces {}, prefix each character with two backslashes.
For example, to use the {and}, enter \\{and\\}.