Auditing
Cerberus FTP Server provides comprehensive logging of all file and user operations and provides both on-screen logging, file logging, and Syslog support. Note: Our log4cxx version does not support TCP Syslogs.
Administrators can quickly view the current log output from the Cerberus UI, or through web administration, by looking at the Log page. The onscreen log will display the most recent log output from Cerberus FTP Server in near real-time.
The server also stores a more extended history of logs on the file system. File-based logging can be managed through an XML configuration file that can control nearly all aspects of how log data is written to a file.
Log File Location
Cerberus FTP Server logging is implemented through the Apache Log4cxx framework, a robust logging package modeled after the popular log4j Java logging package. The default configuration logs up to 5000KB of data to a single file and then rolls over to a new log file. The past 10 log files are kept by default but log file size, naming, and history are all completely configurable through the log4j.xml file.
The log is located under:
C:\ProgramData\Cerberus LLC\Cerberus FTP Server\log
You can also open the log file by simply clicking on the Show button on the Log page as demonstrated below:
Configuring File Logging
File logging is controlled by an XML configuration file named log4j.xml. You can find this file at C:\ProgramData\Cerberus LLC\Cerberus FTP Server\log4j.xml
Using the log4j.xml file you can:
- Add loggers that rollover every day
- Change the default size of log files for size-based logging
- Change the number of log files kept for size-based logging
- Add a Syslog logger
- Change the formatting of log output
You can also have a combination of these different logging methods. The basic component of the logging package is the log appender. You can have a size-based log appender, a daily rolling log appender, or a Syslog appender.
The following example log4j.xml file contains a size-based log appender that rolls over after the log file reaches a certain maximum size, and that limits the number of log files that are kept. These types of loggers are limited to at most 13 saved log files. There is also a separate log file for logging only errors.
<?xml version="1.0" encoding="UTF-8" ?> <log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="false"> <!-- A Size-based log file that rolls over to a new file after 5000KB and keeps at most 5 log files --> <appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender"> <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy" > <param name="activeFileName" value="log/server.log" /> <param name="fileNamePattern" value="log/server.%i.log" /> <param name="minIndex" value="1" /> <param name="maxIndex" value="5" /> </rollingPolicy> <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy"> <param name="maxFileSize" value="5000KB" /> </triggeringPolicy> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n" /> </layout> </appender> <!-- Add an appender that logs all errors to a separate log file --> <appender name="ERROR_FILE" class="org.apache.log4j.rolling.RollingFileAppender"> <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy"> <param name="activeFileName" value="log/server_error.log"/> <param name="fileNamePattern" value="log/server_error.%i.log"/> </rollingPolicy> <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy"> <param name="maxFileSize" value="5000KB"/> </triggeringPolicy> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - %m%n"/> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="LevelMin" value="ERROR" /> </filter> </appender> <root> <level value="INFO" class="org.apache.log4j.xml.XLevel" /> <appender-ref ref="FILE"/> <appender-ref ref="ERROR_FILE"/> </root> </log4j:configuration>
Possible values for the <level value=”level” class=”org.apache.log4j.xml.XLevel” /> tag’s level parameter are:
- TRACE
- DEBUG
- INFO
- WARN
- ERROR
Note!: There MUST be an 'appender-ref' entry to the <root> object for each appender you add to your log4j file. The 'ref' value corresponds to the appender 'name' parameter. For example, in the example above, there are two appenders:
<appender name="FILE"
and
<appender name="ERROR_FILE"
As you can see, there are two entries in the <root> object:
<root> <level value="INFO" class="org.apache.log4j.xml.XLevel" />
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
Each 'appender-ref' entry refers to one of the appenders added to the log4j.
Example Syslog log4j.xml Configuration File
The below logfile example shows a Syslog logger.
<?xml version="1.0" encoding="UTF-8" ?> <log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="false"> <!-- Add a Syslog appender --> <appender name="syslog" class="org.apache.log4j.net.SyslogAppender"> <param name="SyslogHost" value="127.0.0.1"/> <param name="Facility" value="USER"/> <param name="FacilityPrinting" value="true"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%t %5r %-5p %-21d{yyyyMMdd HH:mm:ss,SSS} %c{2} [%x] %m %n"/> </layout> </appender> <root> <level value="INFO" class="org.apache.log4j.xml.XLevel" /> <appender-ref ref="syslog"/> </root> </log4j:configuration>
Example Daily Rollover log4j.xml Configuration File
The below logfile example shows a simple daily rollover logger.
<?xml version="1.0" encoding="UTF-8" ?> <log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="false"> <!-- Add a Daily log file appender that will roll over to a new log file each night --> <appender name="DAILY_ROLL" class="org.apache.log4j.rolling.RollingFileAppender"> <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy"> <param name="FileNamePattern" value="log/daily_server.%d{yyyy-MM-dd}.log"/> </rollingPolicy> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n" /> </layout> </appender> <root> <level value="INFO" class="org.apache.log4j.xml.XLevel" /> <appender-ref ref="DAILY_ROLL"/> </root> </log4j:configuration>
Log File Filtering
You can edit existing appenders, or add new appenders to your log file to do things like capture errors or IP blocks only or filter out unwanted IP addresses from services like health checkers. See note above about ensuring you have added one entry into the <root> object per appender you've added to your log4j.
Example IP Filter Appender
The below appender example filters out an IP address. Change the "client.ip" parameter to the IP you wish to filter out
<!-- ######################################-->
<!-- Application Daily Roll Appender With IP Filter -->
<!-- ######################################-->
<appender name="DAILY_ERROR_ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="log/server_error.%d{dd-MMM-yyyy}.log"/>
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n" />
</layout>
<filter class="MapFilter">
<param name="client.ip" value="100.100.100.100" />
<param name="AcceptOnMatch" value="false" />
</filter>
</appender>
Example Error Log Appender
The below appender example shows a simple error-only logger.
<!-- ######################################-->
<!-- Application Error Log Daily Roll Appender -->
<!-- ######################################-->
<appender name="DAILY_ERROR_ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="log/server_error.%d{dd-MMM-yyyy}.log"/>
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="ERROR" />
</filter>
</appender>
Example IP Blocked Filter Log Appender
The below appender outputs a log file with IP Blocks Only.
<!-- ######################################-->
<!-- IP BLOCKS Log Appender -->
<!-- ######################################-->
<appender name="IPBLOCKSLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/IPBlocks.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Never Block" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="IP Address has been automatically blocked" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Geolocated IP" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Geolocate IP" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="auto-blocked" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="DOS" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example Password Changes Appender
The below appender captures only password changes.
<!-- ######################################-->
<!-- PASSWORD UPDATES Log Appender -->
<!-- ######################################-->
<appender name="PASSWORDUPDATESLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/PasswordUpdates.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Password changed for user" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example MFA Changes Appender
The below appender captures only multi-factor authentication changes.
<!-- ######################################-->
<!-- MFA UPDATES Log Appender -->
<!-- ######################################-->
<appender name="MFAUPDATESLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/MFAUpdates.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Two factor authentication is now enabled for user account" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Disabled 2FA for user" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="2FA" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example User Updates Appender
The below appender captures only user updates.
<!-- ######################################-->
<!-- User Updates Log Appender -->
<!-- ######################################-->
<appender name="USERUPDATESLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/UserUpdates.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Virtual directory" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="updated" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example Authentication Errors Appender
The below appender captures only authentication errors.
<!-- ######################################-->
<!-- Authentication Errors Log Appender -->
<!-- ######################################-->
<appender name="AUTHERRORSLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/AuthenticationErrors.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to find authentication methods for user" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to find directory object" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Could not authenticate Native user" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to retrieve attributes for AD user" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example Connection Errors Appender
The below appender captures only connection errors.
<!-- ######################################-->
<!-- Connection Errors Log Appender -->
<!-- ######################################-->
<appender name="CONNECTIONERRORSLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/ConnectionErrors.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="SSL accept error: An I/O error occurred" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to establish secure HTTPS connection" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Global Request Message: keepalive@jcraft.com, Want Reply: 1" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="SSL connection using TLSv1.1" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example Operations Errors Appender
The below appender captures only operations errors such as unable to open, delete, create, stats.
<!-- ######################################-->
<!-- Server Operations Errors Log Appender -->
<!-- ######################################-->
<appender name="SERVEROPERATIONSERRORSLOGFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="fileNamePattern" value="log/ServerOperationsErrors.%d{dd-MMM-yyyy}.log" />
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n"/>
</layout>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to open" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to delete file" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to create directory" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to delete directory" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Unable to open file handle to local file" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="StringMatchFilter">
<param name="StringToMatch" value="Stat failed for" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="DenyAllFilter" />
</appender>
Example appender with filter that removes entries for specified IP address
This is an example of a size-based rolling log4j XML with a filter to remove entries with a specified IP address (for example to stop logging connections from a health checker). See 'MapFilter' for location of the filtering XML:
<?xml version="1.0" encoding="UTF-8" ?> <log4j:configuration xmlns:log4j='http://logging.apache.org/' debug="false"> <!-- A Size-based log file that rolls over to a new file after 5000KB --> <appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender">
<param name="encoding" value="UTF-8" />
<param name="threshold" value="INFO" />
<rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
<param name="activeFileName" value="log/server.log" />
<param name="fileNamePattern" value="log/server.%i.log" />
<param name="minIndex" value="1" />
<param name="maxIndex" value="10" />
</rollingPolicy>
<triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
<param name="maxFileSize" value="5000KB" />
</triggeringPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}]:%7.7p [%6.6x] - [%X{client.ip}]:%X{client.user} - %m%n" />
</layout>
<filter class="MapFilter">
<param name="client.ip" value="100.100.100.100" /> <!-- Replace with IP to remove from logs -->
<param name="AcceptOnMatch" value="false" />
</filter>
</appender> <root>
<level value="INFO" class="org.apache.log4j.xml.XLevel" />
<appender-ref ref="FILE" />
</root>
</log4j:configuration>
Log File Location and Naming
You can change the location and name of the file created under the various log appenders using the appropriate field. For the default RollingFileAppender logger with a FixedWindowRollingPolicy you will need to change both the activeFileName and fileNamePattern parameters in the log4j.xml file. For the DailyRollingFileAppender you will just need to change the File parameter associated with the logger.
If using a relative log file path, the path is relative to the C:\ProgramData\Cerberus LLC\Cerberus FTP Server
folder.
Logging Settings in Server Manager
In addition to the file-based log, Cerberus displays the current log output to the graphical user interface while the server is running. Options for screen-based logging can be controlled through the Logging settings tab of the Server Manager.
Root Log Level
Controls the root log level for all log appenders. All log appenders inherit the root log level as their lowest threshold. The default level is INFO.
Log appenders can be set at a higher log level threshold than the root logger but cannot be set at a lower level. For example, if the Syslog appender is set to DEBUG, but the root log level is set to INFO, the Syslog will still only write out log information at the INFO level.
The DEBUG level is for troubleshooting, and the root log level should not be left at this level for regular production use because of the excessive logging produced.
Syslog Support
Cerberus FTP Server supports Syslog integration. Administrators can control Syslog settings from this page. Note: Our log4cxx version does not support TCP Syslog.
Enable Syslog logging | Enable syslog logging |
Syslog Host | The address of the machine hosting the syslog server. |
Syslog Facility | The syslog facility value that should be associated with the syslog events. |
Syslog logging levels:
DEBUG |
The DEBUG level designates fine-grained informational events that are most useful to debug an application. |
INFO | The INFO level designates informational messages that highlight the progress of the application at coarse-grained level. |
WARN | The WARN level designates potentially harmful situations. |
ERROR | The ERROR level designates error events that might still allow the application to continue running. |
FATAL | The FATAL level designates very severe error events that will presumably lead the application to abort. |
Comments
0 comments
Article is closed for comments.