Restructure repository to manage both server2 and caddy-vps
- Create server2/ directory and migrate Xray proxy config, Clash config, and utility scripts - Create caddy-vps/ directory and add Caddyfile reverse proxy configuration - Update .gitea/workflows/deploy.yml CI/CD pipeline to validate JSON/YAML and check Caddyfile formatting/syntax - Deploy configurations sequentially to both servers - Update README.md to document multi-server topology and CI/CD behavior Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,38 @@
|
||||
mixed-port: 7890
|
||||
allow-lan: false
|
||||
mode: rule
|
||||
log-level: info
|
||||
|
||||
dns:
|
||||
enable: true
|
||||
enhanced-mode: fake-ip
|
||||
nameserver:
|
||||
- https://dns.google/dns-query
|
||||
- https://cloudflare-dns.com/dns-query
|
||||
|
||||
proxies:
|
||||
- name: Japan-VPS
|
||||
type: vless
|
||||
server: 158.101.140.85
|
||||
port: 443
|
||||
uuid: 7bb711be-47a2-4273-aa8e-45bcb6216f70
|
||||
network: tcp
|
||||
tls: true
|
||||
udp: true
|
||||
flow: xtls-rprx-vision
|
||||
servername: www.microsoft.com
|
||||
reality-opts:
|
||||
public-key: 203MXpq2G45goHJB7gmdEorwORVeyBOvEISlcLCrWms
|
||||
short-id: abcd1234
|
||||
client-fingerprint: safari
|
||||
|
||||
proxy-groups:
|
||||
- name: Proxy
|
||||
type: select
|
||||
proxies:
|
||||
- Japan-VPS
|
||||
- DIRECT
|
||||
|
||||
rules:
|
||||
- GEOIP,CN,DIRECT
|
||||
- MATCH,Proxy
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
# VPS Hardening Script for oracle-tokyo
|
||||
# Based on Security Audit 2026-02-14
|
||||
|
||||
set -e
|
||||
|
||||
echo "Starting VPS hardening..."
|
||||
|
||||
# 1. Disable X11Forwarding in SSH
|
||||
if grep -q "^X11Forwarding yes" /etc/ssh/sshd_config; then
|
||||
echo "Disabling X11Forwarding..."
|
||||
sudo sed -i 's/^X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config
|
||||
sudo systemctl restart ssh
|
||||
else
|
||||
echo "X11Forwarding already disabled."
|
||||
fi
|
||||
|
||||
# 2. Restrict Xray config permissions
|
||||
XRAY_CONFIG="/usr/local/etc/xray/config.json"
|
||||
if [ -f "$XRAY_CONFIG" ]; then
|
||||
CURRENT_PERMS=$(stat -c "%a" "$XRAY_CONFIG")
|
||||
if [ "$CURRENT_PERMS" != "600" ]; then
|
||||
echo "Restricting permissions on $XRAY_CONFIG to 600..."
|
||||
sudo chmod 600 "$XRAY_CONFIG"
|
||||
else
|
||||
echo "Xray config permissions already restricted."
|
||||
fi
|
||||
else
|
||||
echo "Xray config not found at $XRAY_CONFIG, skipping."
|
||||
fi
|
||||
|
||||
# 3. Close port 80 in iptables if open
|
||||
if sudo iptables -L INPUT -n | grep -q "dpt:80"; then
|
||||
echo "Closing port 80 in iptables..."
|
||||
sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT || true
|
||||
else
|
||||
echo "Port 80 already closed in iptables."
|
||||
fi
|
||||
|
||||
# 4. Disable shells for default cloud users (opc, ubuntu)
|
||||
for user in opc ubuntu; do
|
||||
if id "$user" &>/dev/null; then
|
||||
CURRENT_SHELL=$(getent passwd "$user" | cut -d: -f7)
|
||||
if [ "$CURRENT_SHELL" != "/usr/sbin/nologin" ]; then
|
||||
echo "Disabling shell for user $user..."
|
||||
sudo usermod -s /usr/sbin/nologin "$user"
|
||||
else
|
||||
echo "Shell for $user already disabled."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 5. AdGuard Home - Ensure bound to private interfaces (Tailscale/Local)
|
||||
AGH_CONFIG="/opt/AdGuardHome/AdGuardHome.yaml"
|
||||
if [ -f "$AGH_CONFIG" ]; then
|
||||
if grep -q "0.0.0.0" "$AGH_CONFIG" | grep -A 5 "bind_hosts"; then
|
||||
echo "WARNING: AdGuard Home might be bound to 0.0.0.0. Manual check recommended in $AGH_CONFIG."
|
||||
# Automatic fix is risky with YAML parsing in bash, so we just warn
|
||||
else
|
||||
echo "AdGuard Home bind hosts check: OK (not 0.0.0.0)."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Hardening complete."
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,154 @@
|
||||
# Issue Fixing Report & VPS Security Audit
|
||||
|
||||
**Date:** 2026-02-14
|
||||
**VPS:** `oracle-tokyo` (158.101.140.85, Ubuntu 24.04, Oracle Cloud Japan)
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Tailscale Exit Node Fix ✅
|
||||
|
||||
### Symptom
|
||||
With Tailscale exit node on, Claude Code / Antigravity / Google failed. Bing worked.
|
||||
|
||||
### Root Cause
|
||||
**GFW DNS poisoning.** Tailscale's DNS servers (Cloudflare `1.1.1.1`, Google `8.8.8.8`) were queried as plaintext UDP, allowing the GFW to intercept and return poisoned IPs.
|
||||
|
||||
### Fixes Applied
|
||||
|
||||
| # | Change | Location | Persistent? |
|
||||
|---|---|---|---|
|
||||
| 1 | UFW forward policy → `ACCEPT` | VPS `/etc/default/ufw` | ✅ |
|
||||
| 2 | NAT MASQUERADE for `ens3` | VPS `/etc/ufw/before.rules` | ✅ |
|
||||
| 3 | DNS nameserver → `100.70.115.1` (AdGuard Home) | Tailscale Admin DNS | ✅ |
|
||||
| 4 | "Use with exit node" → ON | Tailscale Admin DNS | ✅ |
|
||||
| 5 | Removed Cloudflare/Google public DNS | Tailscale Admin DNS | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Part 2: VPS Security Audit
|
||||
|
||||
### ✅ Things That Are Good
|
||||
|
||||
| Item | Status |
|
||||
|---|---|
|
||||
| SSH root login | Disabled ✅ |
|
||||
| SSH password auth | Disabled ✅ |
|
||||
| fail2ban | Active, 108 IPs banned historically ✅ |
|
||||
| Unattended upgrades | Enabled, last update Feb 13 ✅ |
|
||||
| `/etc/shadow` permissions | Properly restricted (`640`) ✅ |
|
||||
| rpcbind | Disabled ✅ |
|
||||
| Kernel | `6.8.0-1026-oracle` (recent) ✅ |
|
||||
| INPUT policy | `DROP` (deny by default) ✅ |
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Security Issues Found
|
||||
|
||||
#### 🔴 HIGH: AdGuard Home DNS exposed publicly on `0.0.0.0:53`
|
||||
|
||||
AdGuard Home binds DNS to **all interfaces** including the public IP `158.101.140.85:53`. This makes your VPS an **open DNS resolver**, which can be abused for DNS amplification DDoS attacks.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Edit /opt/AdGuardHome/AdGuardHome.yaml
|
||||
# Change:
|
||||
# bind_hosts:
|
||||
# - 0.0.0.0
|
||||
# To:
|
||||
# bind_hosts:
|
||||
# - 100.70.115.1
|
||||
# - 127.0.0.1
|
||||
sudo systemctl restart AdGuardHome
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> An open DNS resolver is one of the most commonly exploited misconfigurations on the internet. This should be fixed immediately. OCI's security list may be blocking port 53 inbound, but defense in depth is critical.
|
||||
|
||||
---
|
||||
|
||||
#### 🟡 MEDIUM: X11Forwarding enabled in SSH
|
||||
|
||||
`X11Forwarding yes` is set in `/etc/ssh/sshd_config`. This is unnecessary for a headless server and expands the attack surface.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
sudo sed -i 's/^X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config
|
||||
sudo systemctl restart sshd
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 🟡 MEDIUM: Xray config world-readable (contains private key)
|
||||
|
||||
`/usr/local/etc/xray/config.json` has permissions `-rw-r--r--` and contains the Reality private key.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
sudo chmod 600 /usr/local/etc/xray/config.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 🟡 MEDIUM: Port 80 open in iptables (nothing listening)
|
||||
|
||||
The INPUT chain accepts traffic on port 80 (386K packets), but nothing is listening. This is leftover from nginx and should be removed to reduce attack surface.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Find and delete the rule
|
||||
sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 🟡 MEDIUM: WireGuard PostUp/PostDown references wrong interface `eth0`
|
||||
|
||||
In `/etc/wireguard/wg0.conf`, the NAT rules reference `eth0` but the actual interface is `ens3`. WireGuard NAT is currently broken.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# Edit /etc/wireguard/wg0.conf
|
||||
# Replace all 'eth0' with 'ens3' in PostUp and PostDown lines
|
||||
sudo wg-quick down wg0 && sudo wg-quick up wg0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 🟢 LOW: `opc` user has a shell
|
||||
|
||||
The default Oracle Cloud `opc` user still has `/bin/sh`. It has no SSH keys but exists as a potential entry point.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
sudo usermod -s /usr/sbin/nologin opc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 🟢 LOW: `ubuntu` user has passwordless sudo
|
||||
|
||||
The cloud-init user `ubuntu` has `NOPASSWD:ALL` sudo. If you don't use it, consider disabling.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
sudo usermod -s /usr/sbin/nologin ubuntu
|
||||
# Or remove the sudoers entry:
|
||||
# sudo rm /etc/sudoers.d/90-cloud-init-users
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Summary of Findings
|
||||
|
||||
| Severity | Issue | Status |
|
||||
|---|---|---|
|
||||
| 🔴 HIGH | AdGuard DNS on `0.0.0.0:53` (open resolver) | ✅ Fixed — bound to `100.70.115.1` + `127.0.0.1` |
|
||||
| 🟡 MED | X11Forwarding enabled | ✅ Fixed — disabled, SSH restarted |
|
||||
| 🟡 MED | Xray config world-readable (has private key) | ✅ Fixed — `chmod 600` |
|
||||
| 🟡 MED | Port 80 open in iptables (unused) | ✅ Fixed — rule removed |
|
||||
| 🟡 MED | WireGuard uses wrong interface `eth0` | ✅ Fixed — changed to `ens3` |
|
||||
| 🟢 LOW | `opc` user has shell | ✅ Fixed — set to nologin |
|
||||
| 🟢 LOW | `ubuntu` user has passwordless sudo | ✅ Fixed — set to nologin |
|
||||
|
||||
> [!TIP]
|
||||
> If you want, I can apply all these fixes for you right now via SSH.
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tailscale Exit Node Setup Script
|
||||
# Automates UFW and IP forwarding requirements
|
||||
|
||||
set -e
|
||||
|
||||
echo "Setting up Tailscale exit node requirements..."
|
||||
|
||||
# 1. Enable IP Forwarding in sysctl
|
||||
if ! grep -q "^net.ipv4.ip_forward=1" /etc/sysctl.conf; then
|
||||
echo "Enabling IPv4 forwarding in sysctl..."
|
||||
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
|
||||
else
|
||||
echo "IPv4 forwarding already enabled."
|
||||
fi
|
||||
|
||||
# 2. Update UFW default forward policy
|
||||
UFW_DEFAULT="/etc/default/ufw"
|
||||
if grep -q 'DEFAULT_FORWARD_POLICY="DROP"' "$UFW_DEFAULT"; then
|
||||
echo "Updating UFW default forward policy to ACCEPT..."
|
||||
sudo sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' "$UFW_DEFAULT"
|
||||
sudo ufw reload
|
||||
else
|
||||
echo "UFW default forward policy is already ACCEPT."
|
||||
fi
|
||||
|
||||
# 3. Add NAT MASQUERADE to UFW before.rules
|
||||
UFW_BEFORE="/etc/ufw/before.rules"
|
||||
if ! grep -q "POSTROUTING -s 100.64.0.0/10 -o ens3 -j MASQUERADE" "$UFW_BEFORE"; then
|
||||
echo "Adding NAT MASQUERADE rule to $UFW_BEFORE..."
|
||||
# This is a bit tricky to automate safely without ruining the file.
|
||||
# We look for the *filter line and insert before it.
|
||||
sudo sed -i '/\*filter/i # NAT rules\n*nat\n:POSTROUTING ACCEPT [0:0]\n-A POSTROUTING -s 100.64.0.0/10 -o ens3 -j MASQUERADE\nCOMMIT\n' "$UFW_BEFORE"
|
||||
sudo ufw reload
|
||||
else
|
||||
echo "NAT MASQUERADE rule already exists in $UFW_BEFORE."
|
||||
fi
|
||||
|
||||
echo "Tailscale exit node setup complete."
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Simple Uptime & Service Health Check for VPS
|
||||
# Checks Xray, AdGuard Home, Tailscale, and WireGuard
|
||||
|
||||
SERVICES=("xray" "AdGuardHome" "tailscaled" "wg-quick@wg0")
|
||||
|
||||
echo "--- Service Health Check ($(date)) ---"
|
||||
|
||||
for svc in "${SERVICES[@]}"; do
|
||||
if systemctl is-active --quiet "$svc"; then
|
||||
echo "[OK] $svc is running"
|
||||
else
|
||||
echo "[ERROR] $svc is NOT running!"
|
||||
# Optional: Attempt restart
|
||||
# sudo systemctl restart "$svc"
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if Xray is listening on 443
|
||||
if ss -tuln | grep -q ":443 "; then
|
||||
echo "[OK] Port 443 is listening (Xray)"
|
||||
else
|
||||
echo "[ERROR] Port 443 is NOT listening!"
|
||||
fi
|
||||
|
||||
# Check if AdGuard Home is listening on 53 (Tailscale IP)
|
||||
TAILSCALE_IP="100.70.115.1"
|
||||
if ss -tuln | grep -q "$TAILSCALE_IP:53 "; then
|
||||
echo "[OK] AdGuard Home is listening on $TAILSCALE_IP:53"
|
||||
else
|
||||
echo "[WARNING] AdGuard Home is NOT listening on $TAILSCALE_IP:53"
|
||||
fi
|
||||
|
||||
echo "--- Check Complete ---"
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": 443,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "7bb711be-47a2-4273-aa8e-45bcb6216f70",
|
||||
"flow": "xtls-rprx-vision"
|
||||
}
|
||||
],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"dest": "www.microsoft.com:443",
|
||||
"serverNames": [
|
||||
"www.microsoft.com"
|
||||
],
|
||||
"privateKey": "8L7hA2XIKkJG9H7CGUsclSqq41UkEuJ6EIH4FioUXl0",
|
||||
"shortIds": [
|
||||
"abcd1234"
|
||||
]
|
||||
}
|
||||
},
|
||||
"sniffing": {
|
||||
"enabled": true,
|
||||
"destOverride": [
|
||||
"http",
|
||||
"tls",
|
||||
"quic"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "direct"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user