├── README.md ├── easytrojan.sh └── mytrojan.sh /README.md: -------------------------------------------------------------------------------- 1 | ![language](https://img.shields.io/badge/language-Shell_&_Go-brightgreen.svg) 2 | ![release](https://img.shields.io/badge/release-v2.0_20221212-blue.svg) 3 | # EasyTrojan # 4 | 5 | #### 世界上最简单的Trojan部署脚本,仅需一行命令即可搭建一台代理服务器 #### 6 | 7 | - 该项目会自动提供trojan服务所需的免费域名与证书,无需购买、解析等繁琐操作 8 | 9 | - 支持RHEL 7、8、9 (CentOS、RedHat、AlmaLinux、RockyLinux)、Debian 9、10、11、12、Ubuntu 16、18、20、22 10 | 11 | - 技术原理不做解释,初衷只为解决个人用户与主机商家被阻断连接的问题,降低大量IP被阻断造成的各种后续影响 12 | 13 | - 该项目仅限研究用途,用户应根据所在管辖区的当地法律评估自己的法规遵从义务 14 | 15 | --- 16 | 17 | #### 首次安装 #### 18 | 请将结尾的password更换为自己的密码,例如 bash easytrojan.sh 123456,安装成功后会返回trojan的连接参数 19 | ``` 20 | curl https://raw.githubusercontent.com/eastmaple/easytrojan/main/easytrojan.sh -o easytrojan.sh && chmod +x easytrojan.sh && bash easytrojan.sh password 21 | ``` 22 | 23 | #### 放行端口 #### 24 | 如果服务器开启了防火墙,应放行TCP80与443端口,如在云厂商的web管理页面有防火墙应同时放行TCP80与443端口 25 | ``` 26 | # RHEL 7、8、9 (CentOS、RedHat、AlmaLinux、RockyLinux) 放行端口命令 27 | firewall-cmd --permanent --add-port=80/tcp --add-port=443/tcp && firewall-cmd --reload && iptables -F 28 | 29 | # Debian 9、10、11、12、Ubuntu 16、18、20、22 放行端口命令 30 | sudo ufw allow proto tcp from any to any port 80,443 && sudo iptables -F 31 | ``` 32 | > 验证端口是否放行 (示例IP应修改为trojan服务器的IP) 33 | > 34 | > 通过浏览器访问脚本提供的免费域名,例如1.3.5.7.nip.io
35 | > 如果自动跳转至https,页面显示Service Unavailable,说明端口已放行 36 | 37 | #### 密码管理 #### 38 | 请将结尾的password更换为自己的密码,仅限字母、数字、下划线,非多密码管理用途无需使用 39 | ``` 40 | # 下载trojan密码管理脚本 41 | curl https://raw.githubusercontent.com/eastmaple/easytrojan/main/mytrojan.sh -o mytrojan.sh && chmod +x mytrojan.sh 42 | 43 | # 创建密码 44 | bash mytrojan.sh add password 45 | 46 | # 一次创建多个密码示例 47 | bash mytrojan.sh add password1 password2 ... 48 | 49 | # 删除密码 50 | bash mytrojan.sh del password 51 | 52 | # 一次删除多个密码示例 53 | bash mytrojan.sh del password1 password2 ... 54 | 55 | # 流量查询 56 | bash mytrojan.sh status password1 password2 ... 57 | 58 | # 流量归零 59 | bash mytrojan.sh rotate 60 | *流量统计归零后会自动在/etc/caddy/trojan/data目录下生成历史记录 61 | 62 | # 密码列表 63 | bash mytrojan.sh list 64 | ``` 65 | 66 | #### 重新安装 #### 67 | ``` 68 | systemctl stop caddy.service && curl https://raw.githubusercontent.com/eastmaple/easytrojan/main/easytrojan.sh -o easytrojan.sh && chmod +x easytrojan.sh && bash easytrojan.sh password 69 | ``` 70 | 71 | #### 完全卸载 #### 72 | ``` 73 | systemctl stop caddy.service && systemctl disable caddy.service && rm -rf /etc/caddy /usr/local/bin/caddy /etc/systemd/system/caddy.service 74 | ``` 75 | 76 | --- 77 | 78 | #### 脚本说明 #### 79 | - 注意事项 80 | 81 | ``` 82 | 必须使用root用户部署 83 | 84 | 请勿修改配置文件参数 85 | ``` 86 | 87 | - 免费域名 88 | 89 | ``` 90 | 通过nip.io提供的免费域名解析服务获取,域名由ServerIP+nip.io组成 91 | 例如你的服务器IP为1.3.5.7,对应的域名则是1.3.5.7.nip.io 92 | ``` 93 | 94 | - 指定域名 95 | 96 | 仅建议在免费域名被阻断时使用 97 | ``` 98 | 在密码后加入域名即可指定域名重新安装,密码与域名之间应使用空格分隔,执行命令如下: 99 | systemctl stop caddy.service && curl https://raw.githubusercontent.com/eastmaple/easytrojan/main/easytrojan.sh -o easytrojan.sh && chmod +x easytrojan.sh && bash easytrojan.sh password yourdomain 100 | 101 | *当指定域名后,如需切换回免费域名,必须完全卸载脚本,重新执行首次安装命令 102 | ``` 103 | 104 | - 更换端口 105 | 106 | 仅建议在443端口被阻断时临时使用 107 | ``` 108 | # 将443端口更换为8443端口示例 109 | sed -i "s/443/8443/g" /etc/caddy/Caddyfile && systemctl restart caddy.service 110 | 111 | *更换端口后应开启对应端口的防火墙 112 | *当测试临时端口超过48小时未阻断后,应尽快更换IP并重新安装,使用默认的443端口 113 | ``` 114 | 115 | - 免费证书 116 | 117 | ``` 118 | 通过Caddy的HTTPS模块实现,会自动申请letsencrypt或zerossl的免费证书 119 | 120 | *关闭防火墙后执行重新安装命令,能大概率解决证书申请失败的问题 121 | 122 | # RHEL 7、8、9 (CentOS、RedHat、AlmaLinux、RockyLinux) 123 | systemctl stop firewalld.service && systemctl disable firewalld.service 124 | 125 | # Debian 9、10、11、Ubuntu 16、18、20、22 126 | sudo ufw disable 127 | ``` 128 | 129 | - 连接参数 130 | 131 | IP为1.3.5.7 密码为123456的服务器示例 132 | ``` 133 | 地址:1.3.5.7.nip.io #根据服务器IP生成(即免费域名) 134 | 端口:443 135 | 密码:123456 #安装时设置的密码 136 | ALPN: h2/http1.1 137 | ``` 138 | 139 | - 服务伪装 140 | 141 | ``` 142 | 非密码正确的trojan客户端访问返回503状态,将trojan伪装成过载的Web服务 143 | ``` 144 | 145 | --- 146 | 147 | #### 连接方式 #### 148 | 149 | 客户端的TLS指纹是导致trojan被封端口的重要原因之一,但问题不仅存在于客户端,服务端也应作出对应配置 150 | 151 | 移动设备建议使用能够开启uTLS指纹功能的客户端,暂未有数据表明其它设备会因未启用uTLS指纹功能被封端口 152 | ``` 153 | 为方便用户理解,配置示例中使用服务器IP:1.3.5.7、密码:123456,实际应修改为trojan服务器真实的连接参数 154 | 155 | 客户端不只局限于以下几种,仅需支持trojan连接即可 156 | ``` 157 | 158 | - 常见客户端连接trojan示例 159 | >- Windows
160 | > [配置示例](https://testingcf.jsdelivr.net/gh/eastmaple/easytrojan@client/v2rayn-trojan.png) | [V2rayN-Core](https://github.com/2dust/v2rayN/releases) | [加速下载](https://ghproxy.com/https://github.com/2dust/v2rayN/releases/download/6.23/v2rayN-With-Core.zip) 161 | >- MacOS
162 | > [配置示例](https://testingcf.jsdelivr.net/gh/eastmaple/easytrojan@client/v2rayu-trojan.png) | [V2rayU](https://github.com/yanue/V2rayU/releases) | [加速下载-64](https://ghproxy.com/https://github.com/yanue/V2rayU/releases/download/v3.8.0/V2rayU-64.dmg) | [加速下载-arm](https://ghproxy.com/https://github.com/yanue/V2rayU/releases/download/v3.8.0/V2rayU-arm64.dmg) 163 | >- Android
164 | > [配置示例](https://testingcf.jsdelivr.net/gh/eastmaple/easytrojan@client/v2rayng-trojan.png) | [V2rayNG](https://github.com/2dust/v2rayNG/releases) | [加速下载](https://ghproxy.com/https://github.com/2dust/v2rayNG/releases/download/1.8.5/v2rayNG_1.8.5.apk) 165 | >- iOS
166 | > [配置示例](https://testingcf.jsdelivr.net/gh/eastmaple/easytrojan@client/shadowrocket-trojan.png) | [Shadowrocket](https://apps.apple.com/us/app/shadowrocket/id932747118) | [AppStore海外代购](https://www.rocketgirls.space/product) 167 | 168 | - OpenWRT passwall [配置示例](https://testingcf.jsdelivr.net/gh/eastmaple/easytrojan@client/passwall-trojan.png) 169 | 170 | - Xray连接trojan部分示例 171 | ``` 172 | { 173 | ... 174 | 175 | "outbounds": [ 176 | { 177 | "protocol": "trojan", 178 | "settings": { 179 | "servers": [ 180 | { 181 | "address": "1.3.5.7", #连接trojan的服务器IP或域名 182 | "port": 443, 183 | "password": "123456" #连接trojan的密码 184 | } 185 | ] 186 | }, 187 | "streamSettings": { 188 | "network": "tcp", 189 | "security": "tls", 190 | "tlsSettings": { 191 | "allowInsecure": false, 192 | "serverName": "1.3.5.7.nip.io", #连接trojan的域名 193 | "fingerprint": "chrome", 194 | "alpn": "h2,http/1.1" 195 | } 196 | } 197 | } 198 | ] 199 | } 200 | ``` 201 | 202 | - Clash连接trojan部分示例(仅限非ARM设备) 203 | ``` 204 | - name: "trojan" 205 | type: trojan 206 | server: 1.3.5.7 207 | port: 443 208 | password: 123456 209 | udp: true 210 | sni: 1.3.5.7.nip.io 211 | alpn: 212 | - h2 213 | - http/1.1 214 | skip-cert-verify: false 215 | ``` 216 | > 警告:请勿在移动设备及其它除Mac外的ARM设备上使用Clash及不包含UTLS指纹功能的客户端连接trojan 217 | 218 | --- 219 | 220 | #### 用户交流 #### 221 | [Telegram Group](https://t.me/easytrojan) 222 | 223 | --- 224 | 225 | #### 数据报告 #### 226 | 227 | 自北京时间2022年10月3日起,不断有中国大陆的用户报告基于TLS的代理服务器被封端口。 228 | 229 | >- 普遍现象:先被封禁443端口,更换端口后会在1~2天的时间内被再次封禁,多次更换端口后服务器IP被阻断 230 | >- 讨论结果:客户端指纹、服务端指纹、连接数量过多、TLS in TLS被识别等,总之众说纷纭,没有解决方案 231 | 232 | 该项目经过多台服务器测试,以及与部分包含trojan协议的客户端开发者沟通,总结出了相对可靠的抗封锁方案,由于用户的客户端、网络环境差异很大,不保证部署后一定不封禁端口。 233 | 234 | > 样本服务器测试数据: 235 | >- 2022年10月初,2台来自境内用户日常使用的Non-TLS代理服务器相继被阻断IP 236 | >- 2022年10月初,2台样本服务器更换为trojan协议,客户端使用路由器连接,稳定运行 237 | >- 2022年10月上,多用户使用移动客户端连接其中1台trojan服务器,必定出现1天内被封端口现象 238 | >- 2022年10月上,排查原因,分析变量,调研多个被封样本,推测出三个最有可能的原因 239 | >- 2022年10月中,逐条更换变量测试,最终确定被封问题来自一个移动端不可描述的原因 240 | >- 2022年10月末,2台服务器在每日约10台设备连接、日流量消耗10~20G的情况下稳定运行 241 | >- 2022年10月末,新购1台封端口重灾区的服务器,并联系了10位使用trojan被封端口的用户,内测该部署方案 242 | >- 2022年11月初,样本服务器中,12台443端口正常,1台被封443端口,原因是客户端跳过了证书验证,更正后稳定运行 243 | >- 2022年11月中,总计13台样本服务器,443端口全部正常,期间有围观用户尝试部署,未收到端口被封反馈 244 | >- 2022年11月末,少量用户在移动设备使用clash客户端连接trojan被封端口,更换为该项目建议的客户端后均稳定运行 245 | >- 2022年11月末,已有超过100台服务器使用该项目部署,暂未收到用户服务器端口被封的反馈 246 | >- 2022年黑色星期五,将该部署方案制作成脚本并发布,并在10天后登上Github Trending总榜 247 | 248 | [![Stargazers over time](https://starchart.cc/eastmaple/easytrojan.svg)](https://starchart.cc/eastmaple/easytrojan) 249 | 250 | --- 251 | 252 | #### 鸣谢项目 #### 253 | [CaddyServer](https://github.com/caddyserver/caddy)
254 | [CaddyTrojan](https://github.com/imgk/caddy-trojan) 255 | -------------------------------------------------------------------------------- /easytrojan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Notes: EasyTrojan for CentOS/RedHat 7+ Debian 9+ and Ubuntu 16+ 4 | # 5 | # Project home page: 6 | # https://github.com/eastmaple/easytrojan 7 | 8 | trojan_passwd=$1 9 | caddy_domain=$2 10 | address_ip=$(curl ipv4.ip.sb) 11 | nip_domain=${address_ip}.nip.io 12 | check_port=$(ss -Hlnp sport = :80 or sport = :443) 13 | 14 | [ "$trojan_passwd" = "" ] && { echo "Error: You must enter a trojan's password to run this script"; exit 1; } 15 | [ "$caddy_domain" != "" ] && domain_ip=$(ping "${caddy_domain}" -c 1 | sed '1{s/[^(]*(//;s/).*//;q}') && [ "$domain_ip" != "$address_ip" ] && { echo "Error: Could not resolve hostname"; exit 1; } 16 | [ "$(id -u)" != "0" ] && { echo "Error: You must be root to run this script"; exit 1; } 17 | [ "$check_port" != "" ] && { echo "Error: Port 80 or 443 is already in use"; exit 1; } 18 | 19 | check_cmd () { command -v "$1" &>/dev/null; } 20 | 21 | if ! check_cmd tar; then 22 | echo "tar: command not found, installing..." 23 | if check_cmd yum; then 24 | yum install -y tar 25 | elif check_cmd apt-get; then 26 | apt-get install -y tar 27 | elif check_cmd dnf; then 28 | dnf install -y tar 29 | else 30 | echo "Error: Unable to install tar"; exit 1 31 | fi 32 | fi 33 | 34 | case $(uname -m) in 35 | x86_64) 36 | caddy_url=https://raw.githubusercontent.com/eastmaple/easytrojan/caddy/caddy_trojan_linux_amd64.tar.gz 37 | ;; 38 | aarch64) 39 | caddy_url=https://raw.githubusercontent.com/eastmaple/easytrojan/caddy/caddy_trojan_linux_arm64.tar.gz 40 | ;; 41 | *) 42 | echo "Error: Your system version does not support" 43 | exit 1 44 | ;; 45 | esac 46 | 47 | curl -L $caddy_url | tar -zx -C /usr/local/bin caddy 48 | 49 | if ! id caddy &>/dev/null; then groupadd --system caddy; useradd --system -g caddy -s "$(command -v nologin)" caddy; fi 50 | 51 | mkdir -p /etc/caddy/trojan && chown -R caddy:caddy /etc/caddy && chmod 700 /etc/caddy 52 | 53 | [ "$caddy_domain" != "" ] && nip_domain=$caddy_domain && rm -rf /etc/caddy/certificates 54 | 55 | cat > /etc/caddy/Caddyfile < /etc/systemd/system/caddy.service <> /etc/caddy/trojan/passwd.txt && sort /etc/caddy/trojan/passwd.txt | uniq > /etc/caddy/trojan/passwd.tmp && mv -f /etc/caddy/trojan/passwd.tmp /etc/caddy/trojan/passwd.txt 122 | 123 | echo "Obtaining and Installing an SSL Certificate..." 124 | count=0 125 | sslfail=0 126 | until [ -d /etc/caddy/certificates ]; do 127 | count=$((count + 1)) 128 | sleep 3 129 | (( count > 20 )) && sslfail=1 && break 130 | done 131 | 132 | [ "$sslfail" = "1" ] && { echo "Certificate application failed, please check your server firewall and network settings"; exit 1; } 133 | 134 | sed -i '/^# End of file/,$d' /etc/security/limits.conf 135 | 136 | cat >> /etc/security/limits.conf <> /etc/sysctl.conf << EOF 198 | fs.file-max = 1048576 199 | fs.inotify.max_user_instances = 8192 200 | net.core.somaxconn = 32768 201 | net.core.netdev_max_backlog = 32768 202 | net.core.rmem_max=33554432 203 | net.core.wmem_max=33554432 204 | net.ipv4.udp_rmem_min=8192 205 | net.ipv4.udp_wmem_min=8192 206 | net.ipv4.tcp_rmem=4096 87380 33554432 207 | net.ipv4.tcp_wmem=4096 16384 33554432 208 | net.ipv4.tcp_syncookies = 1 209 | net.ipv4.tcp_fin_timeout = 30 210 | net.ipv4.tcp_tw_reuse = 1 211 | net.ipv4.ip_local_port_range = 1024 65000 212 | net.ipv4.tcp_max_syn_backlog = 16384 213 | net.ipv4.tcp_max_tw_buckets = 6000 214 | net.ipv4.route.gc_timeout = 100 215 | net.ipv4.tcp_syn_retries = 1 216 | net.ipv4.tcp_synack_retries = 1 217 | net.ipv4.tcp_timestamps = 0 218 | net.ipv4.tcp_max_orphans = 32768 219 | net.ipv4.tcp_no_metrics_save = 1 220 | net.ipv4.tcp_ecn = 0 221 | net.ipv4.tcp_frto = 0 222 | net.ipv4.tcp_mtu_probing = 0 223 | net.ipv4.tcp_rfc1337 = 0 224 | net.ipv4.tcp_sack = 1 225 | net.ipv4.tcp_fack = 1 226 | net.ipv4.tcp_window_scaling = 1 227 | net.ipv4.tcp_adv_win_scale = 1 228 | net.ipv4.tcp_moderate_rcvbuf = 1 229 | net.ipv4.tcp_keepalive_time = 600 230 | net.ipv4.tcp_notsent_lowat = 16384 231 | net.ipv4.conf.all.route_localnet = 1 232 | net.ipv4.ip_forward = 1 233 | net.ipv4.conf.all.forwarding = 1 234 | net.ipv4.conf.default.forwarding = 1 235 | EOF 236 | 237 | modprobe tcp_bbr &>/dev/null 238 | if grep -wq bbr /proc/sys/net/ipv4/tcp_available_congestion_control; then 239 | echo "net.core.default_qdisc = fq" >>/etc/sysctl.conf 240 | echo "net.ipv4.tcp_congestion_control = bbr" >>/etc/sysctl.conf 241 | fi 242 | 243 | sysctl -p 244 | 245 | check_http=$(curl -L http://"$nip_domain") 246 | [ "$check_http" != "Service Unavailable" ] && { echo "You have installed EasyTrojan 2.0,please enable TCP port 80 and 443"; exit 1; } 247 | 248 | clear 249 | 250 | echo "You have successfully installed EasyTrojan 2.0" && echo "Address: $nip_domain | Port: 443 | Password: $trojan_passwd | Alpn: h2,http/1.1" 251 | -------------------------------------------------------------------------------- /mytrojan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Notes: EasyMyTrojan for CentOS/RedHat 7+ Debian 9+ and Ubuntu 16+ 4 | # 5 | # Project home page: 6 | # https://github.com/eastmaple/easytrojan 7 | 8 | [ "$(id -u)" != "0" ] && { echo "Error: You must be root to run this script"; exit 1; } 9 | 10 | case $1 in 11 | add) 12 | shift 13 | for i in "$@" ; do 14 | if curl -X POST -H "Content-Type: application/json" -d "{\"password\": \"$i\"}" http://127.0.0.1:2019/trojan/users/add ; then 15 | echo "$i" >> /etc/caddy/trojan/passwd.txt && 16 | sort /etc/caddy/trojan/passwd.txt | uniq > /etc/caddy/trojan/passwd.tmp && 17 | mv -f /etc/caddy/trojan/passwd.tmp /etc/caddy/trojan/passwd.txt && 18 | echo "Add Succeeded" 19 | else 20 | echo "Add $i Failed" 21 | fi 22 | done 23 | ;; 24 | del) 25 | shift 26 | for i in "$@" ; do 27 | if curl -X DELETE -H "Content-Type: application/json" -d "{\"password\": \"$i\"}" http://127.0.0.1:2019/trojan/users/delete ; then 28 | sed -i "/^${i}$/d" /etc/caddy/trojan/passwd.txt && 29 | echo "Delete Succeeded" 30 | else 31 | echo "Delete $i Failed" 32 | fi 33 | done 34 | ;; 35 | status) 36 | shift 37 | for i in "$@" ; do 38 | hash=$(echo -n "$i" | sha224sum | cut -d ' ' -f1) 39 | echo "$i data usage: $(cat /etc/caddy/trojan/"$hash")" 40 | done 41 | ;; 42 | rotate) 43 | mkdate=$(date +%Y%m%d-%H%M%S) 44 | cpdate=$(find /etc/caddy/trojan -maxdepth 1 -type f -not -path "*passwd.txt*") 45 | mkdir -p /etc/caddy/trojan/data/"$mkdate" 46 | for alldate in $cpdate; do 47 | cp -f "$alldate" /etc/caddy/trojan/data/"$mkdate" && 48 | sed -i -r -e "s|[0-9]+|0|g" "$alldate" 49 | done 50 | echo "Clear all data usage successful" 51 | ;; 52 | list) 53 | cat /etc/caddy/trojan/passwd.txt 54 | ;; 55 | *) 56 | echo "Command Examples:" 57 | echo "./mytrojan.sh add passwd1 passwd2 ..." 58 | echo "./mytrojan.sh del passwd1 passwd2 ..." 59 | echo "./mytrojan.sh status passwd1 passwd2 ..." 60 | echo "./mytrojan.sh rotate" 61 | echo "./mytrojan.sh list" 62 | ;; 63 | esac 64 | --------------------------------------------------------------------------------