Outline VPN Cheatsheet¶
Outline VPN ist eine Open-Source-VPN-Lösung, die von Jigsaw (ein Tochterunternehmen von Alphabet Inc.) entwickelt wurde, die die Benutzerfreundlichkeit, Sicherheit und Widerstand gegen Blockierung priorisiert. Im Shadowsocks Protokoll gebaut, bietet Outline eine einfache Möglichkeit, persönliche VPN-Server zu erstellen und zu verwalten, während sie starke Verschlüsselungs- und Obfuskationsmöglichkeiten bieten, die es für Netzwerkadministratoren schwierig machen, den VPN-Verkehr zu erkennen und zu blockieren.
Überblick¶
Architektur und Design Philosophie¶
Outline VPN besteht aus zwei Hauptkomponenten: dem Outline Manager für die Serververwaltung und dem Outline Client für Endbenutzer-Konnektivität. Das System ist mit Einfachheit und Sicherheit als Kernprinzipien konzipiert, so dass es Benutzern ohne umfangreiche technische Kenntnisse und unter Beibehaltung von unternehmenseigenen Sicherheitsstandards zugänglich ist.
Der Outline Manager ist eine Desktop-Anwendung, mit der Administratoren Outline-Server auf verschiedenen Cloud-Plattformen wie DigitalOcean, Google Cloud Platform, Amazon Web Services und Vultr bereitstellen und verwalten können. Der Manager behandelt Serverbereitstellung, Benutzer-Schlüsselerzeugung und Verkehrsüberwachung über eine intuitive grafische Schnittstelle.
Die Outline Client-Anwendungen sind für Windows-, macOS-, Linux-, iOS- und Android-Plattformen verfügbar. Diese Clients nutzen die generierten Zugangsschlüssel, um sichere Verbindungen zu Outline-Servern herzustellen, um verschlüsselte Tunnelings für alle Netzwerk-Verkehrs.
Schlüsselmerkmale¶
```bash
Core Outline VPN Capabilities¶
- Shadowsocks-based protocol for enhanced obfuscation
- Automatic server deployment on major cloud platforms
- Simple access key sharing system
- Cross-platform client applications
- Traffic monitoring and usage analytics
- Resistance to deep packet inspection (DPI)
- No logging policy and privacy-focused design
- Open-source transparency and auditability ```_
Serverinstallation und Setup¶
Automatische Serverinstallation¶
```bash
Install Outline server on Ubuntu/Debian¶
The installation script will:¶
1. Install Docker and Docker Compose¶
2. Download and run the Outline server container¶
3. Generate initial configuration¶
4. Display management API URL and certificate fingerprint¶
Verify installation¶
sudo docker ps|grep outline
Check server status¶
sudo docker logs outline-server
View server configuration¶
sudo cat /opt/outline/access.txt
Manual Docker installation (alternative method)¶
sudo docker run -d \ --name outline-server \ --restart unless-stopped \ -p 443:443/tcp \ -p 443:443/udp \ -p 8080:8080/tcp \ -v outline-data:/root/shadowbox/persisted-state \ quay.io/outline/shadowbox:stable
Configure firewall for Outline server¶
sudo ufw allow 443/tcp sudo ufw allow 443/udp sudo ufw allow 8080/tcp sudo ufw enable
Enable IP forwarding¶
echo 'net.ipv4.ip_forward=1'|sudo tee -a /etc/sysctl.conf echo 'net.ipv6.conf.all.forwarding=1'|sudo tee -a /etc/sysctl.conf sudo sysctl -p ```_
Bereitstellung von Cloud Platform¶
```bash
DigitalOcean deployment script¶
!/bin/bash¶
DROPLET_NAME="outline-vpn-server" REGION="nyc3" SIZE="s-1vcpu-1gb" IMAGE="ubuntu-20-04-x64"
Create droplet¶
doctl compute droplet create $DROPLET_NAME \ --region $REGION \ --size $SIZE \ --image $IMAGE \ --ssh-keys $(doctl compute ssh-key list --format ID --no-header|tr '\n' ',') \ --wait
Get droplet IP¶
DROPLET_IP=$(doctl compute droplet list --format Name,PublicIPv4 --no-header|grep $DROPLET_NAME|awk '\\{print $2\\}')
Install Outline server¶
ssh root@$DROPLET_IP 'curl -sS https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh|bash'
AWS EC2 deployment with Terraform¶
cat > outline-server.tf ``<< 'EOF' provider "aws" \{ region = "us-east-1" \}
resource "aws_instance" "outline_server" \{ ami = "ami-0c02fb55956c7d316" # Ubuntu 20.04 LTS instance_type = "t3.micro" key_name = "your-key-pair"
vpc_security_group_ids = [aws_security_group.outline_sg.id]
user_data = <<-EOF #!/bin/bash curl -sS https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh|bash EOF
tags = \{ Name = "Outline VPN Server" \} \}
resource "aws_security_group" "outline_sg" \{ name_prefix = "outline-server-"
ingress \{ from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] \}
ingress \{ from_port = 443 to_port = 443 protocol = "udp" cidr_blocks = ["0.0.0.0/0"] \}
ingress \{ from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] \}
ingress \{ from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] \}
egress \{ from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] \} \}
output "server_ip" \{ value = aws_instance.outline_server.public_ip \} EOF
Deploy with Terraform¶
terraform init terraform plan terraform apply ```_
Docker komponiert Setup¶
```yaml
docker-compose.yml for Outline server¶
version: '3.8'
services: outline-server: image: quay.io/outline/shadowbox:stable container_name: outline-server restart: unless-stopped ports: - "443:443/tcp" - "443:443/udp" - "8080:8080/tcp" volumes: - outline-data:/root/shadowbox/persisted-state - /etc/letsencrypt:/etc/letsencrypt:ro environment: - SB_API_PORT=8080 - SB_CERTIFICATE_FILE=/etc/letsencrypt/live/your-domain.com/fullchain.pem - SB_PRIVATE_KEY_FILE=/etc/letsencrypt/live/your-domain.com/privkey.pem networks: - outline-network
watchtower: image: containrrr/watchtower container_name: outline-watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock command: --interval 86400 outline-server networks: - outline-network
volumes: outline-data:
networks: outline-network: driver: bridge ```_
Outline Manager Konfiguration¶
Initial Setup und Serververbindung¶
```bash
Download Outline Manager¶
Windows: https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Manager.exe¶
macOS: https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Manager.dmg¶
Linux: https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Manager.AppImage¶
Connect to existing server using management API¶
Format: https://server-ip:8080/management-api-url¶
Example connection string from server installation:¶
\{"apiUrl":"https://192.168.1.100:8080/management-api-url","certSha256":"certificate-fingerprint"\}¶
Verify server connection¶
curl -k -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/server"
Get server information¶
curl -k -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/server/info"
Example response:¶
\{¶
"name": "Outline Server",¶
"serverId": "server-id-123",¶
"metricsEnabled": true,¶
"createdTimestampMs": 1640995200000,¶
"version": "1.8.0",¶
"accessKeyDataLimit": null,¶
"portForNewAccessKeys": 443¶
\}¶
```_
Schlüsselverwaltung¶
```bash
Create new access key¶
curl -k -X POST \ -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/access-keys"
Example response:¶
\{¶
"id": "0",¶
"name": "User 1",¶
"password": "password123",¶
"port": 443,¶
"method": "chacha20-ietf-poly1305",¶
"accessUrl": "ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZDEyMw@192.168.1.100:443/?outline=1"¶
\}¶
List all access keys¶
curl -k -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/access-keys"
Rename access key¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"name": "John Doe"\}' \ "https://your-server-ip:8080/management-api-url/access-keys/0/name"
Set data limit for access key (in bytes)¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"limit": \{"bytes": 10737418240\}\}' \ "https://your-server-ip:8080/management-api-url/access-keys/0/data-limit"
Remove data limit¶
curl -k -X DELETE \ "https://your-server-ip:8080/management-api-url/access-keys/0/data-limit"
Delete access key¶
curl -k -X DELETE \ "https://your-server-ip:8080/management-api-url/access-keys/0"
Get access key metrics¶
curl -k -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/metrics/transfer"
Example metrics response:¶
\{¶
"bytesTransferredByUserId": \{¶
"0": 1073741824,¶
"1": 2147483648¶
\}¶
\}¶
```_
Serverkonfiguration¶
```bash
Change server name¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"name": "Company VPN Server"\}' \ "https://your-server-ip:8080/management-api-url/server/name"
Set default port for new access keys¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"port": 8443\}' \ "https://your-server-ip:8080/management-api-url/server/port-for-new-access-keys"
Enable/disable metrics collection¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"metricsEnabled": true\}' \ "https://your-server-ip:8080/management-api-url/server/metrics-enabled"
Set server-wide data limit¶
curl -k -X PUT \ -H "Content-Type: application/json" \ -d '\{"limit": \{"bytes": 107374182400\}\}' \ "https://your-server-ip:8080/management-api-url/server/access-key-data-limit"
Get server configuration¶
curl -k -H "Content-Type: application/json" \ "https://your-server-ip:8080/management-api-url/server" ```_
Client Konfiguration und Nutzung¶
Windows Client Setup¶
```powershell
Download and install Outline Client for Windows¶
$OutlineClientUrl = "https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Client.exe" \(OutlineClientPath = "\)env:TEMP\Outline-Client.exe"
Invoke-WebRequest -Uri $OutlineClientUrl -OutFile $OutlineClientPath Start-Process -FilePath $OutlineClientPath -Wait
Import access key via command line (if supported)¶
Note: Outline Client primarily uses GUI for key import¶
Access key format: ss://base64-encoded-config@server:port/?outline=1¶
Example access key:¶
ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZDEyMw@192.168.1.100:443/?outline=1¶
Registry settings for Outline Client (advanced configuration)¶
$OutlineRegPath = "HKCU:\Software\Outline" if (!(Test-Path $OutlineRegPath)) \{ New-Item -Path $OutlineRegPath -Force \}
Set auto-connect on startup¶
Set-ItemProperty -Path $OutlineRegPath -Name "AutoConnect" -Value 1
Configure proxy settings¶
Set-ItemProperty -Path $OutlineRegPath -Name "ProxyMode" -Value "auto" ```_
macOS Client Setup¶
```bash
Download Outline Client for macOS¶
curl -L -o "Outline-Client.dmg" \ "https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Client.dmg"
Mount and install¶
hdiutil mount Outline-Client.dmg cp -R "/Volumes/Outline Client/Outline Client.app" /Applications/ hdiutil unmount "/Volumes/Outline Client"
Launch Outline Client¶
open "/Applications/Outline Client.app"
Import access key via URL scheme (if supported)¶
open "ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZDEyMw@192.168.1.100:443/?outline=1"
Configure system proxy settings¶
networksetup -setautoproxyurl "Wi-Fi" "http://127.0.0.1:1080/proxy.pac"
Check VPN connection status¶
scutil --nc list|grep -i outline ```_
Linux Client Setup¶
```bash
Download Outline Client AppImage¶
wget -O Outline-Client.AppImage \ "https://github.com/Jigsaw-Code/outline-client/releases/latest/download/Outline-Client.AppImage"
chmod +x Outline-Client.AppImage
Run Outline Client¶
./Outline-Client.AppImage
Alternative: Install via Snap¶
sudo snap install outline-client
Create desktop entry¶
cat >~/.local/share/applications/outline-client.desktop
<< 'EOF'
[Desktop Entry]
Name=Outline Client
Comment=Outline VPN Client
Exec=/path/to/Outline-Client.AppImage
Icon=outline-client
Terminal=false
Type=Application
Categories=Network;Security;
EOF
Configure system-wide proxy (Ubuntu/Debian)¶
gsettings set org.gnome.system.proxy mode 'auto' gsettings set org.gnome.system.proxy autoconfig-url 'http://127.0.0.1:1080/proxy.pac'
Configure iptables for VPN traffic (advanced)¶
sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 1080 sudo iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 1080 ```_
Mobile Client Konfiguration¶
```bash
iOS Configuration¶
1. Download Outline app from App Store¶
2. Tap "Add Server" or "+"¶
3. Scan QR code or paste access key¶
4. Tap "Connect"¶
Generate QR code for access key (server-side)¶
qrencode -t PNG -o access-key-qr.png \ "ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZDEyMw@192.168.1.100:443/?outline=1"
Android Configuration¶
1. Download Outline app from Google Play Store¶
2. Tap "Add Server"¶
3. Scan QR code or manually enter access key¶
4. Tap "Connect"¶
Android ADB commands for automation (requires root)¶
adb shell am start -a android.intent.action.VIEW \ -d "ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTpwYXNzd29yZDEyMw@192.168.1.100:443/?outline=1" \ org.outline.android.client ```_
Erweiterte Konfiguration¶
Individuelle Schatten Konfiguration¶
```bash
Manual Shadowsocks server configuration¶
cat >`` /etc/shadowsocks-libev/config.json << 'EOF' \\{ "server": "0.0.0.0", "server_port": 443, "password": "your-strong-password", "timeout": 300, "method": "chacha20-ietf-poly1305", "fast_open": false, "workers": 1, "prefer_ipv6": false, "no_delay": true, "reuse_port": true, "mode": "tcp_and_udp" \\} EOF
Install Shadowsocks-libev¶
sudo apt update sudo apt install shadowsocks-libev
Start Shadowsocks server¶
sudo systemctl enable shadowsocks-libev sudo systemctl start shadowsocks-libev
Configure multiple ports for load balancing¶
cat > /etc/shadowsocks-libev/multi-port.json << 'EOF' \\{ "server": "0.0.0.0", "port_password": \\{ "443": "password1", "8443": "password2", "9443": "password3" \\}, "timeout": 300, "method": "chacha20-ietf-poly1305", "fast_open": false \\} EOF
Advanced obfuscation with simple-obfs¶
sudo apt install simple-obfs
cat > /etc/shadowsocks-libev/obfs-config.json << 'EOF' \\{ "server": "0.0.0.0", "server_port": 443, "password": "your-password", "timeout": 300, "method": "chacha20-ietf-poly1305", "plugin": "obfs-server", "plugin_opts": "obfs=tls;obfs-host=www.google.com" \\} EOF ```_
Lastausgleich und hohe Verfügbarkeit¶
```bash
HAProxy configuration for multiple Outline servers¶
cat > /etc/haproxy/haproxy.cfg << 'EOF' global daemon maxconn 4096
defaults mode tcp timeout connect 5000ms timeout client 50000ms timeout server 50000ms
frontend outline_frontend bind *:443 default_backend outline_servers
backend outline_servers balance roundrobin server outline1 192.168.1.101:443 check server outline2 192.168.1.102:443 check server outline3 192.168.1.103:443 check EOF
Start HAProxy¶
sudo systemctl enable haproxy sudo systemctl start haproxy
Nginx stream proxy for load balancing¶
cat > /etc/nginx/nginx.conf << 'EOF' events \\{ worker_connections 1024; \\}
stream \\{ upstream outline_backend \\{ server 192.168.1.101:443; server 192.168.1.102:443; server 192.168.1.103:443; \\}
server \\\\{
listen 443;
proxy_pass outline_backend;
proxy_timeout 1s;
proxy_responses 1;
\\\\}
\\} EOF
Keepalived for high availability¶
cat > /etc/keepalived/keepalived.conf << 'EOF' vrrp_script chk_outline \\{ script "/usr/local/bin/check_outline.sh" interval 2 weight -2 fall 3 rise 2 \\}
vrrp_instance VI_1 \\{ state MASTER interface eth0 virtual_router_id 51 priority 101 advert_int 1 authentication \\{ auth_type PASS auth_pass outline123 \\} virtual_ipaddress \\{ 192.168.1.100 \\} track_script \\{ chk_outline \\} \\} EOF
Health check script¶
cat > /usr/local/bin/check_outline.sh << 'EOF'
!/bin/bash¶
curl -k --connect-timeout 5 https://localhost:8080/management-api-url/server >/dev/null 2>&1 exit $? EOF
chmod +x /usr/local/bin/check_outline.sh ```_
Sicherheitshärten¶
```bash
Firewall configuration with iptables¶
!/bin/bash¶
Flush existing rules¶
iptables -F iptables -X iptables -t nat -F iptables -t nat -X
Default policies¶
iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
Allow loopback¶
iptables -A INPUT -i lo -j ACCEPT
Allow established connections¶
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Allow SSH (change port as needed)¶
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Allow Outline VPN¶
iptables -A INPUT -p tcp --dport 443 -j ACCEPT iptables -A INPUT -p udp --dport 443 -j ACCEPT iptables -A INPUT -p tcp --dport 8080 -s 192.168.1.0/24 -j ACCEPT
Enable NAT for VPN clients¶
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -A FORWARD -i tun+ -j ACCEPT iptables -A FORWARD -o tun+ -j ACCEPT
Rate limiting for SSH¶
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
Save rules¶
iptables-save > /etc/iptables/rules.v4
Fail2ban configuration for additional security¶
cat > /etc/fail2ban/jail.local << 'EOF' [DEFAULT] bantime = 3600 findtime = 600 maxretry = 3
[sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log
[outline-api] enabled = true port = 8080 filter = outline-api logpath = /var/log/outline/access.log maxretry = 5 EOF
Create custom filter for Outline API¶
cat > /etc/fail2ban/filter.d/outline-api.conf << 'EOF'
[Definition]
failregex = ^
SSL/TLS certificate with Let's Encrypt¶
sudo apt install certbot
Generate certificate¶
sudo certbot certonly --standalone -d your-domain.com
Configure automatic renewal¶
echo "0 12 * * * /usr/bin/certbot renew --quiet"|sudo crontab -
Update Outline server to use SSL certificate¶
sudo docker exec outline-server \ sh -c 'echo "SB_CERTIFICATE_FILE=/etc/letsencrypt/live/your-domain.com/fullchain.pem" >> /opt/outline/environment' sudo docker exec outline-server \ sh -c 'echo "SB_PRIVATE_KEY_FILE=/etc/letsencrypt/live/your-domain.com/privkey.pem" >> /opt/outline/environment'
sudo docker restart outline-server ```_
Überwachung und Fehlerbehebung¶
Serverüberwachung¶
```bash
Monitor Outline server logs¶
sudo docker logs -f outline-server
Monitor system resources¶
htop iotop nethogs
Check network connections¶
sudo netstat -tulpn|grep :443 sudo ss -tulpn|grep :443
Monitor bandwidth usage¶
vnstat -i eth0 iftop -i eth0
Custom monitoring script¶
cat > /usr/local/bin/outline-monitor.sh << 'EOF'
!/bin/bash¶
LOG_FILE="/var/log/outline-monitor.log" API_URL="https://localhost:8080/management-api-url"
Function to log with timestamp¶
log_message() \\{ echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE \\}
Check server health¶
check_server_health() \\{ if curl -k -s "$API_URL/server" >/dev/null 2>&1; then log_message "Server health check: OK" return 0 else log_message "Server health check: FAILED" return 1 fi \\}
Check Docker container status¶
check_container_status() \\{ if docker ps|grep -q outline-server; then log_message "Container status: Running" return 0 else log_message "Container status: Not running" return 1 fi \\}
Get transfer metrics¶
get_transfer_metrics() \\{ METRICS=\((curl -k -s "\)API_URL/metrics/transfer" 2>/dev/null) if [ $? -eq 0 ]; then log_message "Transfer metrics: $METRICS" else log_message "Failed to retrieve transfer metrics" fi \\}
Main monitoring loop¶
main() \\{ log_message "Starting Outline monitoring"
if ! check_container_status; then
log_message "Attempting to restart Outline server"
docker restart outline-server
sleep 10
fi
if check_server_health; then
get_transfer_metrics
else
log_message "Server health check failed, investigating..."
docker logs --tail 50 outline-server >> $LOG_FILE
fi
\\}
main EOF
chmod +x /usr/local/bin/outline-monitor.sh
Add to crontab for regular monitoring¶
echo "*/5 * * * * /usr/local/bin/outline-monitor.sh"|crontab - ```_
Leistungsoptimierung¶
```bash
Optimize TCP settings for VPN performance¶
cat > /etc/sysctl.d/99-outline-performance.conf << 'EOF'
TCP optimization¶
net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 net.ipv4.tcp_rmem = 4096 87380 134217728 net.ipv4.tcp_wmem = 4096 65536 134217728 net.ipv4.tcp_congestion_control = bbr net.core.default_qdisc = fq
Network buffer optimization¶
net.core.netdev_max_backlog = 5000 net.core.netdev_budget = 600
Connection tracking optimization¶
net.netfilter.nf_conntrack_max = 1048576 net.netfilter.nf_conntrack_tcp_timeout_established = 7200
IP forwarding and routing¶
net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 EOF
Apply settings¶
sudo sysctl -p /etc/sysctl.d/99-outline-performance.conf
Docker container resource limits¶
sudo docker update --memory=1g --cpus=2 outline-server
Optimize Shadowsocks configuration for performance¶
cat > /opt/outline/shadowsocks-optimized.json << 'EOF' \\{ "server": "0.0.0.0", "server_port": 443, "password": "your-password", "timeout": 300, "method": "chacha20-ietf-poly1305", "fast_open": true, "workers": 4, "prefer_ipv6": false, "no_delay": true, "reuse_port": true, "mode": "tcp_and_udp" \\} EOF ```_
Probleme bei der Fehlerbehebung¶
```bash
Connection issues troubleshooting¶
1. Check server accessibility¶
ping your-server-ip telnet your-server-ip 443
2. Verify DNS resolution¶
nslookup your-domain.com dig your-domain.com
3. Check firewall rules¶
sudo iptables -L -n sudo ufw status
4. Test port connectivity¶
nc -zv your-server-ip 443 nc -zuv your-server-ip 443
Client connection debugging¶
Enable debug logging in Outline client¶
# Windows: %APPDATA%\Outline\logs\
macOS: ~/Library/Logs/Outline/¶
Linux: ~/.config/Outline/logs/¶
Server-side debugging¶
sudo docker exec -it outline-server /bin/bash cat /var/log/shadowbox.log
Network troubleshooting¶
Check routing table¶
ip route show route -n
Monitor network traffic¶
sudo tcpdump -i any port 443 sudo tcpdump -i any host your-client-ip
Check for packet loss¶
mtr your-server-ip
Bandwidth testing¶
iperf3 -s # On server iperf3 -c your-server-ip # On client
Certificate issues¶
openssl s_client -connect your-server-ip:443 -servername your-domain.com openssl x509 -in /etc/letsencrypt/live/your-domain.com/fullchain.pem -text -noout
Reset Outline server configuration¶
sudo docker stop outline-server sudo docker rm outline-server sudo rm -rf /opt/outline/
Reinstall using installation script¶
```_
Automatisierung und Schrift¶
Automatisierte Bereitstellung Script¶
```bash
!/bin/bash¶
Automated Outline VPN deployment script¶
set -e
Configuration variables¶
SERVER_NAME="Outline VPN Server" DOMAIN_NAME="" EMAIL="" CLOUD_PROVIDER="digitalocean" # digitalocean, aws, gcp, vultr REGION="nyc3" SIZE="s-1vcpu-1gb"
Colors for output¶
RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color
Logging function¶
log() \\{ echo -e "\(\\\\{GREEN\\\\}[\)(date +'%Y-%m-%d %H:%M:%S')]$\\{NC\\} $1" \\}
error() \\{ echo -e "\(\\\\{RED\\\\}[ERROR]\)\\{NC\\} $1" >&2 exit 1 \\}
warning() \\{ echo -e "\(\\\\{YELLOW\\\\}[WARNING]\)\\{NC\\} $1" \\}
Check prerequisites¶
check_prerequisites() \\{ log "Checking prerequisites..."
# Check if running as root
if [[ $EUID -eq 0 ]]; then
error "This script should not be run as root"
fi
# Check required commands
for cmd in curl docker docker-compose; do
if ! command -v $cmd &> /dev/null; then
error "$cmd is required but not installed"
fi
done
log "Prerequisites check passed"
\\}
Install Docker if not present¶
install_docker() \\{ if ! command -v docker &> /dev/null; then log "Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh sudo usermod -aG docker $USER rm get-docker.sh log "Docker installed successfully" fi \\}
Deploy Outline server¶
deploy_outline() \\{ log "Deploying Outline server..."
# Create outline directory
sudo mkdir -p /opt/outline
cd /opt/outline
# Download and run installation script
curl -sS https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh|sudo bash
# Wait for server to start
sleep 30
# Check if server is running
if sudo docker ps|grep -q outline-server; then
log "Outline server deployed successfully"
else
error "Failed to deploy Outline server"
fi
\\}
Configure SSL certificate¶
configure_ssl() \\{ if [[ -n "\(DOMAIN_NAME" && -n "\)EMAIL" ]]; then log "Configuring SSL certificate for $DOMAIN_NAME..."
# Install certbot
sudo apt update
sudo apt install -y certbot
# Stop outline server temporarily
sudo docker stop outline-server
# Generate certificate
sudo certbot certonly --standalone -d $DOMAIN_NAME --email $EMAIL --agree-tos --non-interactive
# Update outline configuration
sudo docker exec outline-server \
sh -c "echo 'SB_CERTIFICATE_FILE=/etc/letsencrypt/live/$DOMAIN_NAME/fullchain.pem' >> /opt/outline/environment"
sudo docker exec outline-server \
sh -c "echo 'SB_PRIVATE_KEY_FILE=/etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem' >> /opt/outline/environment"
# Restart outline server
sudo docker start outline-server
# Setup auto-renewal
echo "0 12 * * * /usr/bin/certbot renew --quiet && docker restart outline-server"|sudo crontab -
log "SSL certificate configured successfully"
else
warning "Domain name or email not provided, skipping SSL configuration"
fi
\\}
Create access keys¶
create_access_keys() \\{ log "Creating initial access keys..."
# Wait for API to be ready
sleep 10
# Get API URL from server
API_URL=$(sudo cat /opt/outline/access.txt|grep -o 'https://[^"]*')
if [[ -n "$API_URL" ]]; then
# Create 3 initial access keys
for i in \\\\{1..3\\\\}; do
RESPONSE=$(curl -k -X POST -H "Content-Type: application/json" "$API_URL/access-keys" 2>/dev/null)
if [[ $? -eq 0 ]]; then
KEY_ID=$(echo $RESPONSE|grep -o '"id":"[^"]*'|cut -d'"' -f4)
ACCESS_URL=$(echo $RESPONSE|grep -o '"accessUrl":"[^"]*'|cut -d'"' -f4)
# Rename the key
curl -k -X PUT -H "Content-Type: application/json" \
-d "\\\\{\"name\": \"User $i\"\\\\}" \
"$API_URL/access-keys/$KEY_ID/name" 2>/dev/null
log "Created access key for User $i: $ACCESS_URL"
fi
done
else
error "Failed to get API URL"
fi
\\}
Setup monitoring¶
setup_monitoring() \\{ log "Setting up monitoring..."
# Create monitoring script
sudo tee /usr/local/bin/outline-health-check.sh > /dev/null << 'EOF'
!/bin/bash¶
API_URL=\((cat /opt/outline/access.txt|grep -o 'https://[^"]*') if curl -k -s "\)API_URL/server" >/dev/null 2>&1; then echo "\((date): Outline server is healthy" else echo "\)(date): Outline server health check failed" docker restart outline-server fi EOF
sudo chmod +x /usr/local/bin/outline-health-check.sh
# Add to crontab
echo "*/5 * * * * /usr/local/bin/outline-health-check.sh >> /var/log/outline-health.log 2>&1"|sudo crontab -
log "Monitoring setup completed"
\\}
Main deployment function¶
main() \\{ log "Starting Outline VPN deployment..."
check_prerequisites
install_docker
deploy_outline
configure_ssl
create_access_keys
setup_monitoring
log "Outline VPN deployment completed successfully!"
log "Server management information:"
sudo cat /opt/outline/access.txt
\\}
Parse command line arguments¶
while [[ \(# -gt 0 ]]; do case \(1 in -d|--domain) DOMAIN_NAME="\)2" shift 2 ;; -e|--email) EMAIL="\)2" shift 2 ;; -h|--help) echo "Usage: $0 [OPTIONS]" echo "Options:" echo " -d, --domain DOMAIN Domain name for SSL certificate" echo " -e, --email EMAIL Email for Let's Encrypt" echo " -h, --help Show this help message" exit 0 ;; *) error "Unknown option: $1" ;; esac done
Run main function¶
main ```_
Bulk User Management¶
```bash
!/bin/bash¶
Bulk user management script for Outline VPN¶
API_URL=$(cat /opt/outline/access.txt|grep -o 'https://[^"]*') USERS_FILE="users.csv"
Create users from CSV file¶
CSV format: username,data_limit_gb¶
create_users_from_csv() \\{ if [[ ! -f "$USERS_FILE" ]]; then echo "Users file not found: $USERS_FILE" exit 1 fi
while IFS=',' read -r username data_limit_gb; do
# Skip header line
if [[ "$username" == "username" ]]; then
continue
fi
echo "Creating user: $username"
# Create access key
RESPONSE=$(curl -k -X POST -H "Content-Type: application/json" "$API_URL/access-keys" 2>/dev/null)
KEY_ID=$(echo $RESPONSE|grep -o '"id":"[^"]*'|cut -d'"' -f4)
ACCESS_URL=$(echo $RESPONSE|grep -o '"accessUrl":"[^"]*'|cut -d'"' -f4)
# Set username
curl -k -X PUT -H "Content-Type: application/json" \
-d "\\\\{\"name\": \"$username\"\\\\}" \
"$API_URL/access-keys/$KEY_ID/name" 2>/dev/null
# Set data limit if specified
if [[ -n "$data_limit_gb" && "$data_limit_gb" != "unlimited" ]]; then
DATA_LIMIT_BYTES=$((data_limit_gb * 1024 * 1024 * 1024))
curl -k -X PUT -H "Content-Type: application/json" \
-d "\\\\{\"limit\": \\\\{\"bytes\": $DATA_LIMIT_BYTES\\\\}\\\\}" \
"$API_URL/access-keys/$KEY_ID/data-limit" 2>/dev/null
fi
echo "User $username created with key ID: $KEY_ID"
echo "Access URL: $ACCESS_URL"
echo "---"
done < "$USERS_FILE"
\\}
Generate usage report¶
generate_usage_report() \\{ echo "Generating usage report..."
# Get all access keys
KEYS=$(curl -k -s "$API_URL/access-keys" 2>/dev/null)
# Get transfer metrics
METRICS=$(curl -k -s "$API_URL/metrics/transfer" 2>/dev/null)
echo "User Usage Report - $(date)"
echo "================================"
printf "%-20s %-10s %-15s\n" "Username" "Key ID" "Data Used (MB)"
echo "--------------------------------"
# Parse and display usage for each user
echo "$KEYS"|jq -r '.accessKeys[]|"\(.id)|\(.name)"'|while IFS='|' read -r key_id username; do
BYTES_USED=$(echo "$METRICS"|jq -r ".bytesTransferredByUserId.\"$key_id\" // 0")
MB_USED=$((BYTES_USED / 1024 / 1024))
printf "%-20s %-10s %-15s\n" "$username" "$key_id" "$MB_USED"
done
\\}
Backup access keys¶
backup_access_keys() \\{ BACKUP_FILE="outline-backup-$(date +%Y%m%d-%H%M%S).json"
echo "Creating backup: $BACKUP_FILE"
# Get all access keys and server info
KEYS=$(curl -k -s "$API_URL/access-keys" 2>/dev/null)
SERVER_INFO=$(curl -k -s "$API_URL/server" 2>/dev/null)
# Create backup JSON
jq -n \
--argjson keys "$KEYS" \
--argjson server "$SERVER_INFO" \
'\\\\{
"backup_date": now|strftime("%Y-%m-%d %H:%M:%S"),
"server_info": $server,
"access_keys": $keys
\\\\}' > "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE"
\\}
Show usage¶
show_usage() \\{ echo "Usage: $0 [COMMAND]" echo "Commands:" echo " create-users Create users from CSV file" echo " usage-report Generate usage report" echo " backup Backup access keys" echo " help Show this help message" \\}
Main script logic¶
case "$1" in create-users) create_users_from_csv ;; usage-report) generate_usage_report ;; backup) backup_access_keys ;; help|--help|-h) show_usage ;; *) echo "Unknown command: $1" show_usage exit 1 ;; esac ```_
Ressourcen¶
- [Offizielle Website des VPN](LINK_5__
- Outline Server GitHub Repository
- Outline Client GitHub Repository
- (___LINK_5__)
- Jigsaw (Google) Offizielle Website