Created on
09-10-2025
02:54 AM
Edited on
09-11-2025
01:17 AM
By
Jean-Philippe_P
This article describes FTP communication through FortiProxy and the required Syntax with CURL.
FortiProxy may also be applicable for FortiGate to some extent.
CURL is a versatile command-line program available for Linux and Windows and is invoked through the command line or the shell interpreter. As such, it can be useful to be called from scripts or for automating such operations.
It describes itself as a program to transfer URL (contents) with various protocols, offers authentication, and cookie handling.
To communicate through FortiProxy using FTP with curl, the command must follow a certain syntax:
curl ftp:// FortiProxyURL -u "FTPusername@serverURL:FTPpassword"
So the command could look like the following:
curl -v ftp:// 10.118.4.229 -u "User1@server.forti.lab:Fortinet123!"
The components explained:
The username also specifies the remote server. This is the instruction for FortiProxy to log in with the given user at (@) the given server, as it otherwise cannot be specified.
FortiProxy will also specify the required format if the syntax is not understood:
< 500-Unrecognized command format. Please provide user and password information according to
< 500-the following format:
< 500- User: [proxy_user:[proxy_passwd:[proxy_token:]]]remote_user@server[:port]
< 500- Pass: [proxy_passwd:[proxy_token:]]remote_passwd
< 500
On FortiProxy, the proxy commands need to go through an FTP proxy policy, which uses the feature for the explicit FTP proxy on FortiProxy. The regular explicit HTTP proxy is not compatible with FTP. Neither protocol is compatible, despite a web server offering an FTP-like view. The following example is such a view that is only HTTP-based. The other examples in this article use the same resources, but communicate with the FTP server process that is running in parallel to the web server.
HTTP webserver
FortiProxy configuration requirement for an explicit FTP proxy is simple:
config system interface
edit "port2"
set vdom "root"
set ip 10.118.4.229 255.255.240.0
set allowaccess ping
set type physical
set explicit-web-proxy enable
set explicit-ftp-proxy enable
next
end
config firewall policy
edit 5
set type explicit-ftp
set name "FTPpolicy"
set dstintf "port1"
set srcaddr "all"
set dstaddr "10.191.19.154"
set action accept
set schedule "always"
set logtraffic all
next
end
Uploading a file will use the --upload-file argument that expects a local filename and path. For example:
curl -v --upload-file testfile1 ftp://10.118.4.229 -u "User1@server.forti.lab:Fortinet123!"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 10.118.4.229:21...
* Connected to 10.118.4.229 (10.118.4.229) port 21
< 220 Welcome to the FortiProxy FTP proxy.
> USER User1@server.forti.lab
< 331-Please provide password information according to the following format:
< 331- [[proxy-passwd:[proxy-token:]]remote_passwd
< 331-
< 331-Please note that we use : as delimiters. Using colons in username or password may result into login failure.
< 331-Please note that if you have provided a proxy-user as part of the user-name,
< 331-you must also provide a proxy-passwd as part of the password. Furthermore,
< 331 proxy-token can only be provided in the password if proxy-user has been provided.
> PASS Fortinet123!
< 230 Login successful.
> PWD
< 257 "/" is current directory.
* Entry path is '/'
* Request has same path as previous transfer
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||64102|)
* Connecting to 10.118.4.229 (10.118.4.229) port 64102
* Trying 10.118.4.229:64102...
* Connected to 10.118.4.229 (10.118.4.229) port 21
> TYPE I
< 200 Type set to I
> STOR testfile1
< 150 Starting data transfer.
} [65536 bytes data]
79 47.6M 0 0 79 37.6M 0 23.0M 0:00:02 0:00:01 0:00:01 23.0M* We are completely uploaded and fine
* Remembering we are in dir ""
< 226 Operation successful
100 47.6M 0 0 100 47.6M 0 18.3M 0:00:02 0:00:02 --:--:-- 18.3M
* Connection #0 to host 10.118.4.229 left intact
Deleting the file requires a different syntax, using the --quote argument. It will hand over the given commands through the FortiProxy. The following example deletes the file that was just uploaded. The FTP server will then handle them as required.
curl -v --quote "DELE testfile1" ftp://10.118.4.229 -u "User1@server.forti.lab:Fortinet123!"
* Trying 10.118.4.229:21...
* Connected to 10.118.4.229 (10.118.4.229) port 21
< 220 Welcome to the FortiProxy FTP proxy.
> USER User1@server.forti.lab
< 331-Please provide password information according to the following format:
< 331- [[proxy-passwd:[proxy-token:]]remote_passwd
< 331-
< 331-Please note that we use : as delimiters. Using colons in username or password may result into login failure.
< 331-Please note that if you have provided a proxy-user as part of the user-name,
< 331-you must also provide a proxy-passwd as part of the password. Furthermore,
< 331 proxy-token can only be provided in the password if proxy-user has been provided.
> PASS Fortinet123!
< 230 Login successful.
> PWD
< 257 "/" is current directory.
* Entry path is '/'
* Request has same path as previous transfer
> DELE testfile1
* ftp_perform ends with SECONDARY: 0
< 250 File deleted successfully.
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||64103|)
* Connecting to 10.118.4.229 (10.118.4.229) port 64103
* Trying 10.118.4.229:64103...
* Connected to 10.118.4.229 (10.118.4.229) port 21
> TYPE A
< 200 Type set to A
> LIST
< 150 Starting data transfer.
* Maxdownload = -1
drwxrwxrwx 1 ftp ftp 0 Sep 10 06:21 file-directory
-rw-rw-rw- 1 ftp ftp 49999452 Sep 10 06:22 testfile
-rw-rw-rw- 1 ftp ftp 3163 Sep 04 09:22 testfile2.log
* Remembering we are in dir ""
< 226 Operation successful
* Connection #0 to host 10.118.4.229 left intact
A regular communication will then look like this, listing the directory contents with the default action, LIST:
curl -v ftp://10.118.4.229 -u "User1@server.forti.lab:Fortinet123!"
* Trying 10.118.4.229:21...
* Connected to 10.118.4.229 (10.118.4.229) port 21
< 220 Welcome to the FortiProxy FTP proxy.
> USER User1@server.forti.lab
< 331-Please provide password information according to the following format:
< 331- [[proxy-passwd:[proxy-token:]]remote_passwd
< 331-
< 331-Please note that we use : as delimiters. Using colons in username or password may result into login failure.
< 331-Please note that if you have provided a proxy-user as part of the user-name,
< 331-you must also provide a proxy-passwd as part of the password. Furthermore,
< 331 proxy-token can only be provided in the password if proxy-user has been provided.
> PASS Fortinet123!
< 230 Login successful.
> PWD
< 257 "/" is current directory.
* Entry path is '/'
* Request has same path as previous transfer
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 229 Entering Extended Passive Mode (|||64104|)
* Connecting to 10.118.4.229 (10.118.4.229) port 64104
* Trying 10.118.4.229:64104...
* Connected to 10.118.4.229 (10.118.4.229) port 21
> TYPE A
< 200 Type set to A
> LIST
< 150 About to start data transfer.
* Maxdownload = -1
drwxrwxrwx 1 ftp ftp 0 Sep 10 06:21 file-directory
-rw-rw-rw- 1 ftp ftp 49999452 Sep 10 06:22 testfile
-rw-rw-rw- 1 ftp ftp 3163 Sep 04 09:22 testfile2.log
* Remembering we are in dir ""
< 226 Operation successful
* Connection #0 to host 10.118.4.229 left intact
FortiProxy will log these sessions on its forward traffic logs (GUI -> Log & Report -> Forward Traffic):
date=2025-09-10 time=10:30:40 eventtime=1757493039413499109 tz="+0200" logid="0000000010" type="traffic" subtype="forward" level="notice" vd="root" srcip=10.118.5.24 srcport=59934 srcintf="port2" srcintfrole="undefined" dstcountry="Reserved" srccountry="Reserved" dstip=10.191.19.154 dstport=57560 dstintf="port1" dstintfrole="undefined" sessionid=22 service="tcp/57560" proxyapptype="ftp-proxy" proto=6 action="accept" policyid=5 policytype="proxy-policy" poluuid="47ab9c60-88d6-51f0-ba46-d4ed7faad010" policyname="FTPpolicy" trandisp="snat" transip=10.191.20.229 transport=59934 clientip=10.118.5.24 duration=39 wanin=191 rcvdbyte=191 wanout=0 lanin=0 sentbyte=0 lanout=191 appcat="unscanned" psrcport=41104 pdstport=21
Note that the passive (PASV) mode is entered by CURL by default and is usually a safe choice. The port referred to in the CURL output with passive mode will, however, not be shown in the FortiProxy logs.
The client's source port is visible as "srcport", the FortiProxy source and destination ports are logged with 'psrcport' and 'pdstport'.
Note as well that the FortiProxy syntax doesn't allow a custom server port. This is because the port in the URL is indicated with a colon ':', which, however, conflicts with the FortiProxy syntax for the username and can be mistaken for the password field.
An example for this syntax with a custom port would look like:
curl -v --upload-file testfile1 ftp://10.118.4.229 -u "User1@server.forti.lab:8021:Fortinet123!"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 10.118.4.229:21...
* Connected to 10.118.4.229 (10.118.4.229) port 21
< 220 Welcome to the FortiProxy FTP proxy.
> USER User1@server.forti.lab
< 331-Please provide password information according to the following format:
< 331- [[proxy-passwd:[proxy-token:]]remote_passwd
< 331-
< 331-Please note that we use : as delimiters. Using colons in username or password may result into login failure.
< 331-Please note that if you have provided a proxy-user as part of the user-name,
< 331-you must also provide a proxy-passwd as part of the password. Furthermore,
< 331 proxy-token can only be provided in the password if proxy-user has been provided.
> PASS 8021:Fortinet123!
< 500-Unrecognized command format. Please provide user and password information according to
< 500-the following format:
< 500- User: [proxy_user:[proxy_passwd:[proxy_token:]]]remote_user@server[:port]
< 500- Pass: [proxy_passwd:[proxy_token:]]remote_passwd
< 500
0 0 0 0 0 0 0 0 --:--:-- 0:00:09 --:--:-- 0
CURL is stuck here and will time out.
For further options and arguments, see the official documentation on CURL: https://curl.se/docs/manpage.html
The Fortinet Security Fabric brings together the concepts of convergence and consolidation to provide comprehensive cybersecurity protection for all users, devices, and applications and across all network edges.
Copyright 2025 Fortinet, Inc. All Rights Reserved.