Restructure repository to manage both server2 and caddy-vps
Deploy / security (push) Failing after 11m14s
Deploy / lint (push) Failing after 12m3s
Deploy / deploy (push) Has been skipped

- 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:
Gan, Jimmy
2026-06-03 03:19:18 +08:00
parent 55a8dbc457
commit 4a91c7a186
11 changed files with 158 additions and 66 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+38
View File
@@ -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
+65
View File
@@ -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

+154
View File
@@ -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.
+42
View File
@@ -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."
+35
View File
@@ -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 ---"
+49
View File
@@ -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"
}
]
}