feat: add deployment script and readmes

This commit is contained in:
Yashar Hosseinpour
2025-06-23 22:15:02 +02:00
commit cf6f0f2c16
4 changed files with 1237 additions and 0 deletions
View File
+259
View File
@@ -0,0 +1,259 @@
<div dir="rtl">
# dnstt-deploy
🚀 **راه‌اندازی و مدیریت سرور dnstt با یک کلیک**
اسکریپت جامع اتوماسیون برای راه‌اندازی و مدیریت سرورهای تونل DNS [dnstt](https://www.bamsoftware.com/software/dnstt) روی سیستم‌های لینوکس. این اسکریپت همه چیز از نصب تا پیکربندی را انجام می‌دهد و راه‌اندازی تونل DNS را بدون دردسر می‌کند.
## راه‌اندازی دامنه DNS
قبل از استفاده از این اسکریپت، باید رکوردهای DNS دامنه خود را به درستی پیکربندی کنید. در اینجا راه‌اندازی مورد نیاز آمده است:
### پیکربندی نمونه
- **نام دامنه شما**: `example.com`
- **آدرس IPv4 سرور شما**: `203.0.113.2`
- **آدرس IPv6 سرور شما**: `2001:db8::2` (اختیاری)
- **زیردامنه تونل**: `t.example.com`
- **نام سرور**: `tns.example.com`
### راه‌اندازی رکوردهای DNS
وارد پنل پیکربندی ثبت‌کننده دامنه خود شوید و این رکوردها را اضافه کنید:
| نوع | نام | اشاره به |
|------|------|-----------|
| A | `tns.example.com` | `203.0.113.2` |
| AAAA | `tns.example.com` | `2001:db8::2` (اگر IPv6 در دسترس باشد) |
| NS | `t.example.com` | `tns.example.com` |
**مهم**: منتظر انتشار DNS بمانید (ممکن است تا 24 ساعت طول بکشد) قبل از تست تونل خود.
## ویژگی‌ها
- **پشتیبانی از چندین توزیع**: Fedora، Rocky Linux، CentOS، Debian، Ubuntu
- **تشخیص خودکار**: تشخیص OS، معماری و پورت SSH
- **امنیت تقویت شده**: اجرای سرویس غیر root با ویژگی‌های امنیتی systemd
- **پیکربندی هوشمند**: تنظیمات پایدار و استفاده مجدد خودکار از کلیدها
- **تونل انعطاف‌پذیر**: حالت SSH یا حالت پروکسی SOCKS
- **آماده شبکه**: پیکربندی خودکار firewall و iptables
- **تأیید باینری**: اعتبارسنجی checksum های MD5، SHA1 و SHA256
- **باینری‌های رسمی**: دانلود از [dnstt.network](https://dnstt.network)
## شروع سریع
### پیش‌نیازها
- سرور لینوکس (Fedora، Rocky، CentOS، Debian یا Ubuntu)
- دسترسی root یا مجوزهای sudo
- اتصال اینترنت برای دانلود بسته‌ها
- **نام دامنه با پیکربندی مناسب DNS** (بخش راه‌اندازی دامنه DNS بالا را ببینید)
### نصب
1. **دانلود اسکریپت:**
```bash
wget https://raw.githubusercontent.com/bugfloyd/dnstt-deploy/main/dnstt-deploy.sh
chmod +x dnstt-deploy.sh
```
2. **اجرای راه‌اندازی:**
```bash
sudo ./dnstt-deploy.sh
```
3. **دنبال کردن راهنمای تعاملی:**
- زیردامنه nameserver خود را وارد کنید (مثل `t.example.com`)
- مقدار MTU را تنظیم کنید (پیش‌فرض: 1232)
- حالت تونل را انتخاب کنید (SSH یا SOCKS)
## پیکربندی
### حالت‌های تونل
**حالت SSH (گزینه 2)**
- ترافیک DNS را به سرویس SSH شما تونل می‌کند
- پورت SSH را به طور خودکار تشخیص می‌دهد (پیش‌فرض: 22)
- عالی برای دسترسی shell امن از طریق DNS
- سازگار با اپلیکیشن‌های موبایل
**حالت SOCKS (گزینه 1)**
- پروکسی SOCKS5 یکپارچه Dante را راه‌اندازی می‌کند
- روی `127.0.0.1:1080` گوش می‌دهد
- قابلیت‌های پروکسی اینترنت کامل فراهم می‌کند
### تنظیمات MTU
- **پیش‌فرض**: 1232 بایت
- **محدوده**: 512-1400 بایت
- **مقادیر توصیه شده**:
- شبکه‌های پایدار/سریع: 1400
- شبکه‌های استاندارد: 1232
- شبکه‌های ناپایدار/کند: 1200
- شبکه‌های موبایل محدود: 512
### تغییر تنظیمات
برای تغییر MTU یا سایر تنظیمات، به سادگی اسکریپت را مجدداً اجرا کنید و مقادیر جدید را وارد کنید. اسکریپت به طور خودکار پیکربندی را بروزرسانی کرده و سرویس‌ها را مجدداً راه‌اندازی می‌کند.
## استفاده از کلاینت
### دانلود باینری کلاینت
باینری مناسب کلاینت dnstt را برای پلتفرم خود از [dnstt.network](https://dnstt.network) دانلود کنید:
**پلتفرم‌های رایج:**
- **Linux x64**: `dnstt-client-linux-amd64`
- **Windows x64**: `dnstt-client-windows-amd64.exe`
- **macOS Intel**: `dnstt-client-darwin-amd64`
- **macOS Apple Silicon**: `dnstt-client-darwin-arm64`
### دستور اتصال
بعد از راه‌اندازی سرور، کلید عمومی دریافت خواهید کرد. از آن برای اتصال استفاده کنید:
```bash
dnstt-client -udp DNS_SERVER_IP:53 -pubkey-file server.pub t.example.com 127.0.0.1:7000
```
#### DNS_SERVER_IP
IP سرور DNS بستگی به سیستم شما دارد:
**Linux**:
```bash
systemd-resolve --status | grep "DNS Servers"
```
گزینه‌های رایج: `127.0.0.53:53`، `127.0.0.1:53` یا IP روتر شما
**Windows**:
```cmd
ipconfig /all | findstr /C:"DNS Servers"
```
**macOS**:
```bash
scutil --dns | grep nameserver
```
همچنین می‌توانید از موارد زیر استفاده کنید:
- IP داخلی روتر/مودم شما (مثل `192.168.1.1:53`)
- IP سرور DNS ارائه‌دهنده اینترنت شما
- سرورهای DNS عمومی مثل `8.8.8.8:53` یا `1.1.1.1:53` (در صورت در دسترس بودن)
### اپلیکیشن‌های موبایل (حالت SSH)
برای تونل‌های SSH، می‌توانید از این اپلیکیشن‌های Android/iOS بدون نیاز به کامپیوتر استفاده کنید:
**Android**:
- [HTTP Injector](https://play.google.com/store/apps/details?id=com.evozi.injector)
- [HTTP Custom](https://play.google.com/store/apps/details?id=xyz.easypro.httpcustom)
- [DarkTunnel](https://play.google.com/store/apps/details?id=net.darktunnel.app)
**iOS**:
- [HTTP Injector](https://apps.apple.com/us/app/http-injector/id1659992827)
## مدیریت
### محل فایل‌ها
```
/usr/local/bin/dnstt-server # باینری اصلی
/etc/dnstt/ # دایرکتوری پیکربندی
├── dnstt-server.conf # پیکربندی اصلی
├── {domain}_server.key # کلید خصوصی (برای هر دامنه)
└── {domain}_server.pub # کلید عمومی (برای هر دامنه)
/etc/systemd/system/dnstt-server.service # سرویس systemd
```
### دستورات سرویس
**سرویس dnstt-server**:
```bash
sudo systemctl status dnstt-server # بررسی وضعیت
sudo systemctl start dnstt-server # شروع سرویس
sudo systemctl stop dnstt-server # توقف سرویس
sudo systemctl restart dnstt-server # راه‌اندازی مجدد سرویس
sudo journalctl -u dnstt-server -f # مشاهده لاگ‌ها
```
**سرویس Dante SOCKS (فقط حالت SOCKS)**:
```bash
sudo systemctl status danted # بررسی وضعیت
sudo systemctl start danted # شروع سرویس
sudo systemctl stop danted # توقف سرویس
sudo systemctl restart danted # راه‌اندازی مجدد سرویس
sudo journalctl -u danted -f # مشاهده لاگ‌ها
```
## عیب‌یابی
### خطاهای اندازه MTU
اگر خطاهایی مثل این می‌بینید:
```
FORMERR: requester payload size 512 is too small (minimum 1232)
```
MTU را به عدد ذکر شده کاهش دهید با اجرای مجدد اسکریپت و وارد کردن مقدار MTU پیشنهادی. مبادلات عملکرد را هنگام استفاده از مقادیر MTU بسیار پایین در نظر بگیرید.
### مشکلات رایج
**سرویس شروع نمی‌شود**:
```bash
sudo systemctl status dnstt-server # بررسی وضعیت سرویس
sudo journalctl -u dnstt-server -n 50 # بررسی لاگ‌ها برای خطاها
ls -la /usr/local/bin/dnstt-server # تأیید مجوزهای باینری
```
**مشکلات پیکربندی DNS**:
```bash
dig @YOUR_SERVER_IP t.mydomain.com # تست تونل DNS (از کلاینت)
sudo iptables -t nat -L PREROUTING -n -v # بررسی قوانین iptables
```
**مشکلات پروکسی SOCKS**:
```bash
curl --socks5 127.0.0.1:1080 http://httpbin.org/ip # تست محلی پروکسی SOCKS
sudo cat /etc/danted.conf # بررسی پیکربندی Dante
```
**بررسی پورت**:
```bash
sudo ss -tulnp | grep 5300 # بررسی پورت dnstt-server
sudo ss -tulnp | grep 1080 # بررسی پورت پروکسی SOCKS (در صورت فعال بودن)
```
## ویژگی‌های پیشرفته
### پشتیبانی از چندین دامنه
اسکریپت از چندین دامنه با ایجاد جفت کلیدهای جداگانه برای هر دامنه پشتیبانی می‌کند. با این حال، تنها یک پیکربندی دامنه می‌تواند در یک زمان فعال باشد زیرا همه پیکربندی‌ها از پورت 53 برای ترافیک DNS استفاده می‌کنند. برای تغییر بین دامنه‌ها، به سادگی اسکریپت را با زیردامنه متفاوت مجدداً اجرا کنید.
### پشتیبانی از DoH و DoT
برای پیکربندی‌های DNS-over-HTTPS (DoH) یا DNS-over-TLS (DoT)، به [مستندات رسمی dnstt](https://dnstt.network) برای دستورالعمل‌های راه‌اندازی دقیق مراجعه کنید.
### نظارت بر عملکرد
```bash
sudo ss -tulnp | grep -E "(5300|1080)" # نظارت بر تعداد اتصالات
sudo systemctl status dnstt-server # بررسی منابع سرویس
sudo journalctl -u dnstt-server -f --no-pager # نظارت بر لاگ‌ها برای خطاها
```
## مشارکت
مشارکت‌ها خوش‌آمد هستند! لطفاً برای ارسال Pull Request احساس راحتی کنید. برای تغییرات بزرگ، لطفاً ابتدا یک issue باز کنید تا در مورد آنچه می‌خواهید تغییر دهید بحث کنیم.
## قدردانی
- [dnstt](https://dnstt.network) توسط David Fifield
- [Dante SOCKS server](https://www.inet.no/dante/) برای قابلیت پروکسی SOCKS
## پشتیبانی
- **مشکلات**: [GitHub Issues](https://github.com/bugfloyd/dnstt-deploy/issues)
- **بحث‌ها**: [GitHub Discussions](https://github.com/bugfloyd/dnstt-deploy/discussions)
- **وب‌سایت رسمی پروژه**: [dnstt.network](https://dnstt.network)
---
**ساخته شده با ❤️ برای حریم خصوصی و امنیت**
</div>
+256
View File
@@ -0,0 +1,256 @@
# dnstt-deploy
🚀 **One-click dnstt server deployment and management**
A comprehensive automation script for deploying and managing [dnstt](https://www.bamsoftware.com/software/dnstt) DNS tunnel servers on Linux systems. This script handles everything from installation to configuration, making DNS tunnel deployment effortless.
## DNS Domain Setup
Before using this script, you need to properly configure your domain's DNS records. Here's the required setup:
### Example Configuration
- **Your domain name**: `example.com`
- **Your server's IPv4 address**: `203.0.113.2`
- **Your server's IPv6 address**: `2001:db8::2` (optional)
- **Tunnel subdomain**: `t.example.com`
- **Server hostname**: `tns.example.com`
### DNS Records Setup
Go into your name registrar's configuration panel and add these records:
| Type | Name | Points to |
|------|------|-----------|
| A | `tns.example.com` | `203.0.113.2` |
| AAAA | `tns.example.com` | `2001:db8::2` (if IPv6 available) |
| NS | `t.example.com` | `tns.example.com` |
**Important**: Wait for DNS propagation (can take up to 24 hours) before testing your tunnel.
## Features
- **Multi-distribution support**: Fedora, Rocky Linux, CentOS, Debian, Ubuntu
- **Automatic detection**: OS, architecture, and SSH port detection
- **Security hardened**: Non-root service execution with systemd security features
- **Smart configuration**: Persistent settings and automatic key reuse
- **Flexible tunneling**: SSH mode or SOCKS proxy mode
- **Network ready**: Automatic firewall and iptables configuration
- **Binary verification**: MD5, SHA1, and SHA256 checksum validation
- **Official binaries**: Downloads from [dnstt.network](https://dnstt.network)
## Quick Start
### Prerequisites
- Linux server (Fedora, Rocky, CentOS, Debian, or Ubuntu)
- Root access or sudo privileges
- Internet connection for package downloads
- **Domain name with proper DNS configuration** (see DNS Domain Setup section above)
### Installation
1. **Download the script:**
```bash
wget https://raw.githubusercontent.com/bugfloyd/dnstt-deploy/main/dnstt-deploy.sh
chmod +x dnstt-deploy.sh
```
2. **Run the deployment:**
```bash
sudo ./dnstt-deploy.sh
```
3. **Follow the interactive prompts:**
- Enter your nameserver subdomain (e.g., `t.example.com`)
- Set MTU value (default: 1232)
- Choose tunnel mode (SSH or SOCKS)
## Configuration
### Tunnel Modes
**SSH Mode (Option 2)**
- Tunnels DNS traffic to your SSH service
- Automatically detects SSH port (default: 22)
- Perfect for secure shell access via DNS
- Compatible with mobile apps
**SOCKS Mode (Option 1)**
- Sets up integrated Dante SOCKS5 proxy
- Listens on `127.0.0.1:1080`
- Provides full internet proxy capabilities
### MTU Settings
- **Default**: 1232 bytes
- **Range**: 512-1400 bytes
- **Recommended values**:
- Stable/Fast networks: 1400
- Standard networks: 1232
- Unstable/Slow networks: 1200
- Restricted mobile networks: 512
### Changing Settings
To change MTU or other settings, simply re-run the script and enter new values. The script will automatically update the configuration and restart services.
## Client Usage
### Download Client Binary
Download the appropriate dnstt client binary for your platform from [dnstt.network](https://dnstt.network):
**Common platforms:**
- **Linux x64**: `dnstt-client-linux-amd64`
- **Windows x64**: `dnstt-client-windows-amd64.exe`
- **macOS Intel**: `dnstt-client-darwin-amd64`
- **macOS Apple Silicon**: `dnstt-client-darwin-arm64`
### Connection Command
After server deployment, you'll receive a public key. Use it to connect:
```bash
dnstt-client -udp DNS_SERVER_IP:53 -pubkey-file server.pub t.example.com 127.0.0.1:7000
```
#### DNS_SERVER_IP
The DNS server IP depends on your system:
**Linux**:
```bash
systemd-resolve --status | grep "DNS Servers"
```
Common options: `127.0.0.53:53`, `127.0.0.1:53`, or your router's IP
**Windows**:
```cmd
ipconfig /all | findstr /C:"DNS Servers"
```
**macOS**:
```bash
scutil --dns | grep nameserver
```
You can also use:
- Your router/modem internal IP (e.g., `192.168.1.1:53`)
- Your ISP's DNS server IP
- Public DNS servers like `8.8.8.8:53` or `1.1.1.1:53` (If Available)
### Mobile Apps (SSH Mode)
For SSH tunnels, you can use these Android/iOS apps without needing a computer:
**Android**:
- [HTTP Injector](https://play.google.com/store/apps/details?id=com.evozi.injector)
- [HTTP Custom](https://play.google.com/store/apps/details?id=xyz.easypro.httpcustom)
- [DarkTunnel](https://play.google.com/store/apps/details?id=net.darktunnel.app)
**iOS**:
- [HTTP Injector](https://apps.apple.com/us/app/http-injector/id1659992827)
## Management
### File Locations
```
/usr/local/bin/dnstt-server # Main binary
/etc/dnstt/ # Configuration directory
├── dnstt-server.conf # Main configuration
├── {domain}_server.key # Private key (per domain)
└── {domain}_server.pub # Public key (per domain)
/etc/systemd/system/dnstt-server.service # Systemd service
```
### Service Commands
**dnstt-server Service**:
```bash
sudo systemctl status dnstt-server # Check status
sudo systemctl start dnstt-server # Start service
sudo systemctl stop dnstt-server # Stop service
sudo systemctl restart dnstt-server # Restart service
sudo journalctl -u dnstt-server -f # View logs
```
**Dante SOCKS Service (SOCKS mode only)**:
```bash
sudo systemctl status danted # Check status
sudo systemctl start danted # Start service
sudo systemctl stop danted # Stop service
sudo systemctl restart danted # Restart service
sudo journalctl -u danted -f # View logs
```
## Troubleshooting
### MTU Size Errors
If you see errors like this:
```
FORMERR: requester payload size 512 is too small (minimum 1232)
```
Lower the MTU to the mentioned number by re-running the script and entering the suggested MTU value. Consider the performance trade-offs when using very low MTU values.
### Common Issues
**Service Won't Start**:
```bash
sudo systemctl status dnstt-server # Check service status
sudo journalctl -u dnstt-server -n 50 # Check logs for errors
ls -la /usr/local/bin/dnstt-server # Verify binary permissions
```
**DNS Configuration Issues**:
```bash
dig @YOUR_SERVER_IP t.mydomain.com # Test DNS tunnel (from client)
sudo iptables -t nat -L PREROUTING -n -v # Check iptables rules
```
**SOCKS Proxy Issues**:
```bash
curl --socks5 127.0.0.1:1080 http://httpbin.org/ip # Test SOCKS proxy locally
sudo cat /etc/danted.conf # Check Dante configuration
```
**Port Check**:
```bash
sudo ss -tulnp | grep 5300 # Check dnstt-server port
sudo ss -tulnp | grep 1080 # Check SOCKS proxy port (if enabled)
```
## Advanced Features
### Multiple Domain Support
The script supports multiple domains by generating separate key pairs for each domain. However, only one domain configuration can be active at a time since all configurations use port 53 for DNS traffic. To switch between domains, simply re-run the script with a different subdomain.
### DoH and DoT Support
For DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT) configurations, refer to the [official dnstt documentation](https://dnstt.network) for detailed setup instructions.
### Performance Monitoring
```bash
sudo ss -tulnp | grep -E "(5300|1080)" # Monitor connection count
sudo systemctl status dnstt-server # Check service resources
sudo journalctl -u dnstt-server -f --no-pager # Monitor logs for errors
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
## Acknowledgments
- [dnstt](https://dnstt.network) by David Fifield
- [Dante SOCKS server](https://www.inet.no/dante/) for SOCKS proxy functionality
## Support
- **Issues**: [GitHub Issues](https://github.com/bugfloyd/dnstt-deploy/issues)
- **Discussions**: [GitHub Discussions](https://github.com/bugfloyd/dnstt-deploy/discussions)
- **Official project website**: [dnstt.network](https://dnstt.network)
---
**Made with ❤️ for privacy and security**
Executable
+722
View File
@@ -0,0 +1,722 @@
#!/bin/bash
# dnstt Server Setup Script
# Supports Fedora, Rocky, CentOS, Debian, Ubuntu
set -e
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "\033[0;31m[ERROR]\033[0m This script must be run as root"
exit 1
fi
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Global variables
DNSTT_BASE_URL="https://dnstt.network"
INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/dnstt"
SYSTEMD_DIR="/etc/systemd/system"
DNSTT_PORT="5300"
DNSTT_USER="dnstt"
CONFIG_FILE="${CONFIG_DIR}/dnstt-server.conf"
# Function to load existing configuration
load_existing_config() {
if [ -f "$CONFIG_FILE" ]; then
print_status "Loading existing configuration..."
# Source the config file to load variables
# shellcheck source=/dev/null
. "$CONFIG_FILE"
return 0
fi
return 1
}
# Function to save configuration
save_config() {
print_status "Saving configuration..."
cat > "$CONFIG_FILE" << EOF
# dnstt Server Configuration
# Generated on $(date)
NS_SUBDOMAIN="$NS_SUBDOMAIN"
MTU_VALUE="$MTU_VALUE"
TUNNEL_MODE="$TUNNEL_MODE"
PRIVATE_KEY_FILE="$PRIVATE_KEY_FILE"
PUBLIC_KEY_FILE="$PUBLIC_KEY_FILE"
EOF
chmod 640 "$CONFIG_FILE"
chown root:"$DNSTT_USER" "$CONFIG_FILE"
print_status "Configuration saved to $CONFIG_FILE"
}
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_question() {
echo -ne "${BLUE}[QUESTION]${NC} $1"
}
# Function to detect OS and package manager
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
else
print_error "Cannot detect OS"
exit 1
fi
# Determine package manager
if command -v dnf &> /dev/null; then
PKG_MANAGER="dnf"
elif command -v yum &> /dev/null; then
PKG_MANAGER="yum"
elif command -v apt &> /dev/null; then
PKG_MANAGER="apt"
else
print_error "Unsupported package manager"
exit 1
fi
print_status "Detected OS: $OS"
print_status "Package manager: $PKG_MANAGER"
}
# Function to detect architecture
detect_arch() {
local arch
arch=$(uname -m)
case $arch in
x86_64)
ARCH="amd64"
;;
aarch64|arm64)
ARCH="arm64"
;;
armv7l|armv6l)
ARCH="arm"
;;
i386|i686)
ARCH="386"
;;
*)
print_error "Unsupported architecture: $arch"
exit 1
;;
esac
print_status "Detected architecture: $ARCH"
}
# Function to check and install required tools
check_required_tools() {
print_status "Checking required tools..."
local required_tools=("curl" "wget" "iptables" "ip6tables")
local missing_tools=()
for tool in "${required_tools[@]}"; do
if ! command -v "$tool" &> /dev/null; then
missing_tools+=("$tool")
fi
done
if [ ${#missing_tools[@]} -gt 0 ]; then
print_status "Installing missing tools: ${missing_tools[*]}"
install_dependencies "${missing_tools[@]}"
else
print_status "All required tools are available"
fi
}
# Function to install dependencies
install_dependencies() {
local tools=("$@")
print_status "Installing dependencies: ${tools[*]}"
case $PKG_MANAGER in
dnf|yum)
$PKG_MANAGER install -y "${tools[@]}" iptables-services
;;
apt)
apt update
apt install -y "${tools[@]}" iptables-persistent
;;
esac
}
# Function to get user input
get_user_input() {
# Load existing configuration if available
local existing_domain=""
local existing_mtu=""
local existing_mode=""
if load_existing_config; then
existing_domain="$NS_SUBDOMAIN"
existing_mtu="$MTU_VALUE"
existing_mode="$TUNNEL_MODE"
print_status "Found existing configuration for domain: $existing_domain"
fi
# Get nameserver subdomain
while true; do
if [[ -n "$existing_domain" ]]; then
print_question "Enter the nameserver subdomain (current: $existing_domain): "
else
print_question "Enter the nameserver subdomain (e.g., t.example.com): "
fi
read -r NS_SUBDOMAIN
# Use existing domain if user just presses enter
if [[ -z "$NS_SUBDOMAIN" && -n "$existing_domain" ]]; then
NS_SUBDOMAIN="$existing_domain"
fi
if [[ -n "$NS_SUBDOMAIN" ]]; then
break
else
print_error "Please enter a valid subdomain"
fi
done
# Get MTU value
if [[ -n "$existing_mtu" ]]; then
print_question "Enter MTU value (current: $existing_mtu): "
else
print_question "Enter MTU value (default: 1232): "
fi
read -r MTU_VALUE
# Use existing MTU if user just presses enter, otherwise use default
if [[ -z "$MTU_VALUE" ]]; then
if [[ -n "$existing_mtu" ]]; then
MTU_VALUE="$existing_mtu"
else
MTU_VALUE="1232"
fi
fi
# Get tunnel mode
while true; do
echo "Select tunnel mode:"
echo "1) SOCKS proxy"
echo "2) SSH mode"
if [[ -n "$existing_mode" ]]; then
local mode_number
if [[ "$existing_mode" == "socks" ]]; then
mode_number="1"
else
mode_number="2"
fi
print_question "Enter choice (current: $mode_number - $existing_mode): "
else
print_question "Enter choice (1 or 2): "
fi
read -r TUNNEL_MODE
# Use existing mode if user just presses enter
if [[ -z "$TUNNEL_MODE" && -n "$existing_mode" ]]; then
TUNNEL_MODE="$existing_mode"
break
fi
case $TUNNEL_MODE in
1)
TUNNEL_MODE="socks"
break
;;
2)
TUNNEL_MODE="ssh"
break
;;
*)
print_error "Invalid choice. Please enter 1 or 2"
;;
esac
done
print_status "Configuration:"
print_status " Nameserver subdomain: $NS_SUBDOMAIN"
print_status " MTU: $MTU_VALUE"
print_status " Tunnel mode: $TUNNEL_MODE"
}
# Function to download and verify dnstt-server
download_dnstt_server() {
local filename="dnstt-server-linux-${ARCH}"
local filepath="${INSTALL_DIR}/dnstt-server"
# Check if file already exists
if [ -f "$filepath" ]; then
print_status "dnstt-server already exists at $filepath"
return 0
fi
print_status "Downloading dnstt-server..."
# Download the binary
curl -L -o "/tmp/$filename" "${DNSTT_BASE_URL}/$filename"
# Download checksums
curl -L -o "/tmp/MD5SUMS" "${DNSTT_BASE_URL}/MD5SUMS"
curl -L -o "/tmp/SHA1SUMS" "${DNSTT_BASE_URL}/SHA1SUMS"
curl -L -o "/tmp/SHA256SUMS" "${DNSTT_BASE_URL}/SHA256SUMS"
# Verify checksums
print_status "Verifying file integrity..."
cd /tmp
# Verify MD5
if md5sum -c <(grep "$filename" MD5SUMS) 2>/dev/null; then
print_status "MD5 checksum verified"
else
print_error "MD5 checksum verification failed"
exit 1
fi
# Verify SHA1
if sha1sum -c <(grep "$filename" SHA1SUMS) 2>/dev/null; then
print_status "SHA1 checksum verified"
else
print_error "SHA1 checksum verification failed"
exit 1
fi
# Verify SHA256
if sha256sum -c <(grep "$filename" SHA256SUMS) 2>/dev/null; then
print_status "SHA256 checksum verified"
else
print_error "SHA256 checksum verification failed"
exit 1
fi
# Move to install directory and make executable
chmod +x "/tmp/$filename"
mv "/tmp/$filename" "$filepath"
print_status "dnstt-server installed successfully"
}
# Function to create dnstt user
create_dnstt_user() {
print_status "Creating dnstt user..."
if ! id "$DNSTT_USER" &>/dev/null; then
useradd -r -s /bin/false -d /nonexistent -c "dnstt service user" "$DNSTT_USER"
print_status "Created user: $DNSTT_USER"
else
print_status "User $DNSTT_USER already exists"
fi
# Create config directory first
mkdir -p "$CONFIG_DIR"
# Set ownership of config directory
chown -R "$DNSTT_USER":"$DNSTT_USER" "$CONFIG_DIR"
chmod 750 "$CONFIG_DIR"
}
# Function to generate keys
generate_keys() {
# Generate key file names based on subdomain
local key_prefix
# shellcheck disable=SC2001
key_prefix=$(echo "$NS_SUBDOMAIN" | sed 's/\./_/g')
PRIVATE_KEY_FILE="${CONFIG_DIR}/${key_prefix}_server.key"
PUBLIC_KEY_FILE="${CONFIG_DIR}/${key_prefix}_server.pub"
# Check if keys already exist for this domain
if [[ -f "$PRIVATE_KEY_FILE" && -f "$PUBLIC_KEY_FILE" ]]; then
print_status "Found existing keys for domain: $NS_SUBDOMAIN"
print_status " Private key: $PRIVATE_KEY_FILE"
print_status " Public key: $PUBLIC_KEY_FILE"
# Verify key ownership and permissions
chown "$DNSTT_USER":"$DNSTT_USER" "$PRIVATE_KEY_FILE" "$PUBLIC_KEY_FILE"
chmod 600 "$PRIVATE_KEY_FILE"
chmod 644 "$PUBLIC_KEY_FILE"
print_status "Using existing keys (verified ownership and permissions)"
else
print_status "Generating new keys for domain: $NS_SUBDOMAIN"
# Generate keys (run as root, then change ownership)
dnstt-server -gen-key -privkey-file "$PRIVATE_KEY_FILE" -pubkey-file "$PUBLIC_KEY_FILE"
# Set proper ownership and permissions
chown "$DNSTT_USER":"$DNSTT_USER" "$PRIVATE_KEY_FILE" "$PUBLIC_KEY_FILE"
chmod 600 "$PRIVATE_KEY_FILE"
chmod 644 "$PUBLIC_KEY_FILE"
print_status "New keys generated:"
print_status " Private key: $PRIVATE_KEY_FILE"
print_status " Public key: $PUBLIC_KEY_FILE"
fi
# Always display public key content
print_status "Public key content:"
cat "$PUBLIC_KEY_FILE"
}
# Function to configure iptables rules
configure_iptables() {
print_status "Configuring iptables rules for DNS redirection..."
# Get the primary network interface
local interface
interface=$(ip route | grep default | awk '{print $5}' | head -1)
if [[ -z "$interface" ]]; then
interface="eth0" # fallback
print_warning "Could not detect network interface, using eth0"
fi
print_status "Using network interface: $interface"
# IPv4 rules
print_status "Setting up IPv4 iptables rules..."
iptables -I INPUT -p udp --dport "$DNSTT_PORT" -j ACCEPT
iptables -t nat -I PREROUTING -i "$interface" -p udp --dport 53 -j REDIRECT --to-ports "$DNSTT_PORT"
# IPv6 rules (if IPv6 is available)
if command -v ip6tables &> /dev/null && [ -f /proc/net/if_inet6 ]; then
print_status "Setting up IPv6 iptables rules..."
ip6tables -I INPUT -p udp --dport "$DNSTT_PORT" -j ACCEPT
ip6tables -t nat -I PREROUTING -i "$interface" -p udp --dport 53 -j REDIRECT --to-ports "$DNSTT_PORT"
else
print_warning "IPv6 not available, skipping ip6tables rules"
fi
# Save iptables rules based on distribution
save_iptables_rules
}
# Function to save iptables rules
save_iptables_rules() {
print_status "Saving iptables rules..."
case $PKG_MANAGER in
dnf|yum)
# For RHEL-based systems
if command -v iptables-save &> /dev/null; then
# Create directory if it doesn't exist
mkdir -p /etc/sysconfig
iptables-save > /etc/sysconfig/iptables
if command -v ip6tables-save &> /dev/null && [ -f /proc/net/if_inet6 ]; then
ip6tables-save > /etc/sysconfig/ip6tables
fi
# Enable and start iptables service
if systemctl list-unit-files | grep -q iptables.service; then
systemctl enable iptables
systemctl enable ip6tables
fi
fi
;;
apt)
# For Debian-based systems
if command -v iptables-save &> /dev/null; then
# Create directory if it doesn't exist
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4
if command -v ip6tables-save &> /dev/null && [ -f /proc/net/if_inet6 ]; then
ip6tables-save > /etc/iptables/rules.v6
fi
fi
;;
esac
}
# Function to configure firewall
configure_firewall() {
print_status "Configuring firewall..."
# Check if firewalld is active
if systemctl is-active --quiet firewalld; then
print_status "Configuring firewalld..."
firewall-cmd --permanent --add-port="$DNSTT_PORT"/udp
firewall-cmd --permanent --add-port=53/udp
firewall-cmd --reload
print_status "Firewalld configured successfully"
# Check if ufw is active
elif systemctl is-active --quiet ufw || ufw status | grep -q "Status: active"; then
print_status "Configuring ufw..."
ufw allow "$DNSTT_PORT"/udp
ufw allow 53/udp
print_status "UFW configured successfully"
else
print_status "No active firewall service detected (firewalld/ufw)"
fi
# Configure iptables rules regardless of firewall service
configure_iptables
}
# Function to detect SSH port
detect_ssh_port() {
local ssh_port
ssh_port=$(ss -tlnp | grep sshd | awk '{print $4}' | cut -d':' -f2 | head -1)
if [[ -z "$ssh_port" ]]; then
# Fallback to default SSH port
ssh_port="22"
fi
echo "$ssh_port"
}
# Function to install and configure Dante SOCKS proxy
setup_dante() {
print_status "Setting up Dante SOCKS proxy..."
# Install Dante
case $PKG_MANAGER in
dnf|yum)
$PKG_MANAGER install -y dante-server
;;
apt)
apt install -y dante-server
;;
esac
# Get the primary network interface for external interface
local external_interface
external_interface=$(ip route | grep default | awk '{print $5}' | head -1)
if [[ -z "$external_interface" ]]; then
external_interface="eth0" # fallback
fi
# Configure Dante
cat > /etc/danted.conf << EOF
# Dante SOCKS server configuration
logoutput: syslog
user.privileged: root
user.unprivileged: nobody
# Internal interface (where clients connect)
internal: 127.0.0.1 port = 1080
# External interface (where connections go out)
external: $external_interface
# Authentication method
socksmethod: none
# Compatibility settings
compatibility: sameport
extension: bind
# Client rules - allow connections from localhost
client pass {
from: 127.0.0.0/8 to: 0.0.0.0/0
log: error
}
# SOCKS rules - allow SOCKS requests to anywhere
socks pass {
from: 127.0.0.0/8 to: 0.0.0.0/0
command: bind connect udpassociate
log: error
}
# Block IPv6 if not properly configured
socks block {
from: 0.0.0.0/0 to: ::/0
log: error
}
client block {
from: 0.0.0.0/0 to: ::/0
log: error
}
EOF
# Enable and start Dante service
systemctl enable danted
systemctl restart danted
print_status "Dante SOCKS proxy configured and started on port 1080"
print_status "External interface: $external_interface"
}
# Function to create systemd service
create_systemd_service() {
print_status "Creating systemd service..."
local service_name="dnstt-server"
local service_file="${SYSTEMD_DIR}/${service_name}.service"
local target_port
if [ "$TUNNEL_MODE" = "ssh" ]; then
target_port=$(detect_ssh_port)
print_status "Detected SSH port: $target_port"
else
target_port="1080" # Dante SOCKS port
fi
# Stop service if it's running to allow reconfiguration
if systemctl is-active --quiet "$service_name"; then
print_status "Stopping existing dnstt-server service for reconfiguration..."
systemctl stop "$service_name"
fi
# Create systemd service file
cat > "$service_file" << EOF
[Unit]
Description=dnstt DNS Tunnel Server
After=network.target
Wants=network.target
[Service]
Type=simple
User=$DNSTT_USER
Group=$DNSTT_USER
ExecStart=${INSTALL_DIR}/dnstt-server -udp :${DNSTT_PORT} -privkey-file ${PRIVATE_KEY_FILE} -mtu ${MTU_VALUE} ${NS_SUBDOMAIN} 127.0.0.1:${target_port}
Restart=always
RestartSec=5
KillMode=mixed
TimeoutStopSec=5
# Security settings
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/
ReadWritePaths=${CONFIG_DIR}
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
[Install]
WantedBy=multi-user.target
EOF
# Reload systemd and enable service
systemctl daemon-reload
systemctl enable "$service_name"
print_status "Systemd service created: $service_name"
print_status "Service will run as user: $DNSTT_USER"
print_status "Service will listen on port: $DNSTT_PORT (redirected from port 53)"
print_status "Service will tunnel to 127.0.0.1:$target_port"
print_status "Mode: $TUNNEL_MODE"
}
# Function to start services
start_services() {
print_status "Starting services..."
# Start dnstt-server service
systemctl start dnstt-server
print_status "dnstt-server service started"
# Show service status
systemctl status dnstt-server --no-pager -l
}
# Function to display final information
display_final_info() {
print_status "=========================="
print_status "Setup completed successfully!"
print_status "=========================="
print_status "Configuration details:"
print_status " Nameserver subdomain: $NS_SUBDOMAIN"
print_status " MTU: $MTU_VALUE"
print_status " Tunnel mode: $TUNNEL_MODE"
print_status " Service user: $DNSTT_USER"
print_status " Listen port: $DNSTT_PORT (DNS traffic redirected from port 53)"
print_status " Private key location: $PRIVATE_KEY_FILE"
print_status " Public key location: $PUBLIC_KEY_FILE"
print_status ""
print_status "Public key content:"
cat "$PUBLIC_KEY_FILE"
print_status ""
print_status "Service management commands:"
print_status " Start: systemctl start dnstt-server"
print_status " Stop: systemctl stop dnstt-server"
print_status " Status: systemctl status dnstt-server"
print_status " Logs: journalctl -u dnstt-server -f"
if [ "$TUNNEL_MODE" = "socks" ]; then
print_status ""
print_status "SOCKS proxy is running on 127.0.0.1:1080"
print_status "Dante service commands:"
print_status " Status: systemctl status danted"
print_status " Stop: systemctl stop danted"
print_status " Start: systemctl start danted"
print_status " Logs: journalctl -u danted -f"
fi
}
# Main function
main() {
print_status "Starting dnstt server setup..."
# Check and install required tools
check_required_tools
# Detect OS and architecture
detect_os
detect_arch
# Get user input
get_user_input
# Download and verify dnstt-server
download_dnstt_server
# Create dnstt user
create_dnstt_user
# Generate keys
generate_keys
# Save configuration after keys are generated
save_config
# Configure firewall and iptables
configure_firewall
# Setup tunnel mode specific configurations
if [ "$TUNNEL_MODE" = "socks" ]; then
setup_dante
else
# If switching from SOCKS to SSH, stop and disable Dante
if systemctl is-active --quiet danted; then
print_status "Switching from SOCKS to SSH mode - stopping Dante service..."
systemctl stop danted
systemctl disable danted
fi
fi
# Create systemd service
create_systemd_service
# Start services
start_services
# Display final information
display_final_info
}
# Run main function
main "$@"