This project provides a complete FTP server and client implementation for cybersecurity education and network analysis. It allows you to observe unencrypted file transfers in Wireshark and understand FTP protocol behavior.
This FTP implementation transmits data unencrypted for educational purposes only. Never use this setup in production environments. Always use encrypted protocols (FTPS/SFTP) for real-world applications.
- Custom logging for all FTP operations (connect, login, upload, download, commands)
- DummyAuthorizer for custom credentials (no Windows user dependency)
- Automatic server directory creation with sample structure
- Configurable permissions and port settings
- Real-time terminal output of all activities
- Comprehensive log file generation
- Command-line interface for quick operations
- Interactive shell mode with FTP-like commands
- Support for upload, download, directory listing, and navigation
- Environment variable configuration
- Both single-machine and multi-machine setup support
- Creates realistic business files (employee records, sales data, system logs)
- Multiple file formats (CSV, JSON, TXT, INI, LOG)
- Dynamic content with randomized data and timestamps
- Varied file sizes for comprehensive FTP testing
- Auto-organized directory structure creation
- Safe fictional data for educational use
- Python 3.7 or higher (current version: 3.13.7)
- Windows, Linux, or macOS
- Administrator privileges (for port binding and firewall configuration)
- Wireshark (for traffic analysis)
From a terminal (PowerShell, CMD, or bash):
-
Create and move into the project folder:
mkdir ftp_cybersec_lab cd ftp_cybersec_lab
-
Clone the repository into the current folder:
git clone https://github.com/golso4243/python-ftp-server-cybersec-lab .β οΈ The trailing . makes sure files are cloned directly into ftp_cybersec_lab instead of a nested folder.
-
Open the project in VS Code:
code .π‘ Tip: Enable the
codecommand- The
codecommand lets you open VS Code from your terminal (e.g., withcode .). - On Windows: During installation of VS Code, check βAdd to PATHβ so the
codecommand works in PowerShell or CMD. - If you missed it, open VS Code, press
Ctrl+Shift+P, search for βShell Command: Install 'code' command in PATHβ, and run it. - After this, restart your terminal and youβll be able to type
code .to open the current folder (ftp_cybersec_lab) in VS Code.
- The
- Set up virtual environment (RECOMMENDED)
- Install Python dependencies:
pip install -r requirements.txt
- Verify installation:
python -c "import pyftpdlib; print('Dependencies installed successfully')"
- Dependency Isolation: Prevents conflicts between different Python projects
- Security: Reduces risk of system-wide package pollution
- Reproducibility: Ensures consistent environment across different systems
- Clean Uninstall: Easy to remove all project dependencies by deleting the virtual environment
# Navigate to project directory
# Skip this step if the project directory is already open in your IDE.
cd ftp_cybersec_lab
# Create virtual environment
python -m venv ftp_lab_venv
# Activate virtual environment
ftp_lab_venv\Scripts\activate
# Verify activation (you should see (ftp_lab_venv) in your prompt)
where python
# Install dependencies
pip install -r requirements.txt
# When done working, deactivate
deactivate# Navigate to project directory
cd ftp_cybersec_lab
# Create virtual environment
python3 -m venv ftp_lab_venv
# Activate virtual environment
source ftp_lab_venv/bin/activate
# Verify activation (you should see (ftp_lab_venv) in your prompt)
which python
# Install dependencies
pip install -r requirements.txt
# When done working, deactivate
deactivate
# Create conda environment
conda create -n ftp_lab_venv python=3.9
# Activate environment
conda activate ftp_lab_venv
# Install dependencies
pip install -r requirements.txt
# Deactivate when done
conda deactivate-
Always activate before working:
# Windows ftp_lab_venv\Scripts\activate # Linux/macOS source ftp_lab_venv/bin/activate
- Verify activation:
- Your command prompt should show
(ftp_lab_venv)prefix python --versionshould show your expected Python versionpip listshould show only project dependencies
- Your command prompt should show
- Update requirements.txt after adding packages:
pip freeze > requirements.txt
- Recreate environment from scratch (if needed):
# Windows # If "rmdir" command does not work > close IDE, delete from folder, reopen IDE, recreate virtual environment rmdir /s ftp_lab_venv python -m venv ftp_lab_venv ftp_lab_venv\Scripts\activate pip install -r requirements.txt # Linux/macOS rm -rf ftp_lab_venv python3 -m venv ftp_lab_venv source ftp_lab_venv/bin/activate pip install -r requirements.txt
- Open project folder in VS Code
- Press
Ctrl+Shift+P(Cmd+Shift+P on Mac) - Type "Python: Select Interpreter"
- Choose the interpreter from your virtual environment:
- Windows:
ftp_lab_venv\Scripts\python.exe - Linux/macOS:
ftp_lab_venv/bin/python
- Windows:
- File β Settings β Project β Python Interpreter
- Click gear icon β Add
- Select "Existing Environment"
- Browse to your virtual environment's Python executable
The project uses .env.development for configuration.
Default settings:
FTP_HOST=127.0.0.1 # Server IP address
FTP_PORT=2121 # FTP port (non-standard for lab safety)
FTP_USER=labuser # FTP username
FTP_PASSWORD=labpass123 # FTP password
FTP_SERVER_ROOT=ftp_server_root # Server directory name
FTP_PERMISSIONS=elradfmwMT # User permissionsBefore running the application, make sure to set up your environment variables.
Copy the development environment .env.development file to .env:
cp .env.development .envcopy .env.development .envYou can delete the .env.development afterwards.
For testing across different machines:
- On the server machine:
- Change
FTP_HOST=0.0.0.0in.envto bind to all interfaces - Note the server's IP address (e.g.,
ipconfigon Windows,ip addron Linux)
- Change
- On the client machine:
- Change
FTP_HOST=<server-ip-address>in.env - Example:
FTP_HOST=192.168.1.100
- Change
- Open Windows Defender Firewall with Advanced Security:
- Press
Win + R, typewf.msc, press Enter - Or search "Windows Defender Firewall with Advanced Security"
- Press
- Create Inbound Rule:
- Right-click "Inbound Rules" β "New Rule..." - Rule Type: Port - Protocol: TCP - Specific Local Ports: 2121 - Action: Allow the connection - Profile: Check all (Domain, Private, Public) - Name: "FTP Lab Server Port 2121" - Description: "Temporary rule for cybersecurity lab - DELETE AFTER USE"
- Create Outbound Rule:
- Right-click "Outbound Rules" β "New Rule..." - Rule Type: Port - Protocol: TCP - Specific Local Ports: 2121 - Action: Allow the connection - Profile: Check all (Domain, Private, Public) - Name: "FTP Lab Client Port 2121" - Description: "Temporary rule for cybersecurity lab - DELETE AFTER USE"
- Allow FTP Data Ports (Passive Mode):
- Create additional inbound/outbound rules for ports 60000-65535 - Or create a rule for "FTP Server" program instead
Run as Administrator:
# Allow inbound FTP control port
netsh advfirewall firewall add rule name="FTP Lab Inbound" dir=in action=allow protocol=TCP localport=2121
# Allow outbound FTP control port
netsh advfirewall firewall add rule name="FTP Lab Outbound" dir=out action=allow protocol=TCP localport=2121
# Allow passive data ports (optional - for better compatibility)
netsh advfirewall firewall add rule name="FTP Lab Data Ports" dir=in action=allow protocol=TCP localport=60000-65535If you encounter permission issues with the FTP server directory:
# Grant full control to the current user
icacls ftp_server_root /grant %USERNAME%:F /T
# Grant read/write permissions to specific user
icacls ftp_server_root /grant "labuser":(OI)(CI)RX /T
# View current permissions
icacls ftp_server_root
# Reset permissions to defaults (if needed)
icacls ftp_server_root /reset /T
# Grant permissions to Everyone (least secure - only for isolated lab)
icacls ftp_server_root /grant Everyone:F /TF= Full controlRX= Read and executeRW= Read and write(OI)= Object inherit(CI)= Container inherit/T= Apply to all files and subdirectories
- Right-click
ftp_server_rootfolder β Properties - Security tab β Edit β Add
- Enter "Everyone" or specific username
- Grant "Full control" permissions
- Apply to subfolders and files
# Windows
ftp_lab_venv\Scripts\activate
# Linux/macOS
source ftp_lab_venv/bin/activatepython ftp_server.pyExpected output:
============================================================
FTP SERVER - CYBERSECURITY LAB
============================================================
Server Host: 127.0.0.1
Server Port: 2121
Username: labuser
Password: labpass123
Server Root: ftp_server_root
Permissions: elradfmwMT
Log File: logs/ftp_server_20240904_143022.log
============================================================
[2024-09-04 14:30:22] Starting FTP server...
Server listening on 127.0.0.1:2121
Press Ctrl+C to stop the server
WARNING: This server transmits data unencrypted for lab purposes!
Monitor traffic with Wireshark on port 2121
------------------------------------------------------------
Confirm FTP services running: netstat -an | findstr 2121
python ftp_client.pyInteractive commands:
FTP> help # Show all commands
FTP> ls # List current directory
FTP> upload test.txt # Upload file
FTP> download welcome.txt # Download file
FTP> cd uploads # Change directory
FTP> pwd # Show current directory
FTP> stats # Show connection status
FTP> quit # Exit client
# Upload files
python ftp_client.py upload local_file.txt
python ftp_client.py upload ftp_test_data/app_config.json uploads/config.json
# Download files
python ftp_client.py download welcome.txt
python ftp_client.py download uploads/config.json local_config.json
# List directories
python ftp_client.py ls
python ftp_client.py ls uploads
# Connect to different server
python ftp_client.py connect 192.168.1.100 2121 testuser testpassUse the provided test data generator script to create realistic files for testing: python generate_test_data.py
This will create the ftp_test_data/ directory in the root folder with the following files:
employee_records.csv- Employee database records (CSV format)app_config.json- Application configuration (JSON format)sales_data.csv- Sales transaction data (CSV format)system.log- System activity logs (LOG format)project_documentation.txt- Project documentation (TXT format)network_config.ini- Network configuration (INI format)
The generator creates realistic test data with various file formats and sizes, perfect for comprehensive FTP testing. All data is fictional and safe for educational use.
Manual Creation (Alternative): If you prefer to create test files manually:
mkdir ftp_test_data
echo "This is a test file for FTP transfer" > ftp_test_data/test.txt
echo "Sensitive document content here" > ftp_test_data/confidential.txt- Open Wireshark
-
Select Network Interface:
- For localhost: Select "Loopback" or "lo0" - For network: Select your network adapter
- Apply Filter:
tcp.port == 2121orftporftp-data
- Start Capture
- Connection establishment: TCP 3-way handshake
- Authentication: USER and PASS commands in plaintext
- Commands: LIST, PWD, CWD, STOR, RETR commands
- Responses: Server response codes (220, 230, 150, 226, etc.)
- File content: Complete file data in plaintext
- Directory listings: Detailed file information
- Passive mode setup: PASV command and data port negotiation
# FTP commands only
ftp.request
# FTP responses only
ftp.response
# File transfer data
ftp-data
# Specific file transfers
ftp-data and tcp contains "filename"
# Authentication attempts
ftp.request.command == "USER" or ftp.request.command == "PASS"
- Credentials transmitted in plaintext
- File contents visible without encryption
- Directory structure exposed
- No integrity protection
Error: 'python' is not recognized as an internal or external command
Solution: Activate virtual environment first:
# Windows
ftp_lab_venv\Scripts\activate
# Linux/macOS
source ftp_lab_venv/bin/activateModuleNotFoundError: No module named 'pyftpdlib'
Solutions:
- Ensure virtual environment is activated
- Install dependencies:
pip install -r requirements.txt - Verify you're in the correct environment:
pip list
Error: Permission denied to bind to port 2121
Solution: Run as administrator or use a port > 1024
Connection failed: [Errno 10061] No connection could be made
Solutions:
- Check if server is running
- Verify firewall rules
- Confirm correct IP/port in configuration
- Try
telnet 127.0.0.1 2121to test basic connectivity
Upload failed: 550 Permission denied
Solutions:
- Check folder permissions with
icacls - Verify FTP_PERMISSIONS in
.env - Ensure server directory exists and is writable
425 Can't open data connection
Solutions:
- Configure firewall for passive ports (60000-65535)
- Check router/NAT settings for multi-machine setup
- Try active mode (less common)
Solutions:
- Verify
.envfile exists - Check file encoding (should be UTF-8)
- Ensure no spaces around
=in env file
- Start server and capture traffic
- Connect client and authenticate
- Analyze: Find credentials in packet capture
- Question: How could this be secured?
- Upload a text file with sensitive content
- Download the same file
- Analyze: Locate file content in packets
- Question: What data leakage risks exist?
- Use wrong credentials multiple times
- Observe server logs and Wireshark
- Analyze: How are failed attempts logged?
- Question: What brute force indicators exist?
- Use different FTP commands (LIST, PWD, CWD)
- Analyze: What system information is revealed?
- Question: How could an attacker map the system?
- Configure server on one machine, client on another
- Analyze traffic between machines
- Question: What additional network risks appear?
deactivateGUI Method:
- Open Windows Defender Firewall with Advanced Security
- Delete "FTP Lab Server Port 2121" rules
- Delete "FTP Lab Client Port 2121" rules
- Delete any passive port rules created
Command Line Method:
# Remove firewall rules
netsh advfirewall firewall delete rule name="FTP Lab Inbound"
netsh advfirewall firewall delete rule name="FTP Lab Outbound"
netsh advfirewall firewall delete rule name="FTP Lab Data Ports"# Windows
rmdir /s ftp_lab_venv
# Linux/macOS
rm -rf ftp_lab_venv
# Windows
rmdir /s ftp_server_root
# Linux/Mac
rm -rf ftp_server_root# Remove all log files
rmdir /s logs # Windows
rm -rf logs # Linux/Mac-
Confirm no FTP services running:
netstat -an | findstr 2121 -
Verify firewall rules removed
-
Check for any remaining test files with sensitive content
ftp_cybersec_lab/
βββ ftp_server.py # Main server application
βββ ftp_client.py # Main client application
βββ generate_test_data.py # Test data generator script
βββ .env # Configuration settings
βββ requirements.txt # Python dependencies
βββ README.md # Project documentation
βββ ftp_lab_venv/ # Virtual environment (created by user)
βββ ftp_server_root/ # Server directory (auto-created)
β βββ uploads/ # Upload destination
β βββ downloads/ # Download source
β βββ shared/ # Shared files
β βββ welcome.txt # Sample file
βββ ftp_test_data/ # Test files (generated)
β βββ employee_records.csv
β βββ app_config.json
β βββ sales_data.csv
β βββ system.log
β βββ project_documentation.txt
β βββ network_config.ini
βββ logs/ # Server logs (auto-created)
βββ ftp_server_*.log # Timestamped log files
- Never use unencrypted FTP in production
- Always use strong authentication mechanisms
- Implement proper access controls and permissions
- Monitor and log all file transfer activities
- Use encrypted protocols (FTPS/SFTP) for real applications
- Regularly audit firewall rules and network access
- Use virtual environments to isolate project dependencies
This lab demonstrates:
- Network protocol analysis techniques
- Plaintext credential interception
- File transfer security risks
- Firewall configuration importance
- System monitoring and logging
- Cybersecurity threat vectors
- Python development best practices
If you encounter issues:
- Ensure virtual environment is activated
- Check the troubleshooting section above
- Verify all prerequisites are met
- Review firewall and permissions settings
- Check server and client logs for detailed error messages
Remember: This is for educational purposes only. Always prioritize security in real-world applications!