trojan-go是trojan的增强版,原版只是把流量套上了tls,trojan-go在此基础上增加了ws混淆方式,支持嵌套其他加密,据说trojan-go比原版优化的好,内存占用更少,速度更快。
配置环境
trojan-go的api跟v2ray一样是grpc,加上软件本身为我们创建了go版的proto文件和服务端,那么我们直接使用go语言来对接api。
安装GO
go下载地址
https://golang.org/dl
根据自己的系统选择对应的go版本。例如linux 64位
wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz
然后将其解压到/usr/local
tar -C /usr/local -zxvf go1.15.6.linux-amd64.tar.gz
添加环境变量
#临时方法
export PATH=$PATH:/usr/local/go/bin
#永久方法
vi /etc/profile #在最后一行添加
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
source /etc/profile #保存退出后
安装必要的包
go get google.golang.org/grpc
go get github.com/p4gefau1t/trojan-go
go get github.com/go-sql-driver/mysql
go get github.com/xtaci/smux
代码实现
首先导入这些包
import (
"fmt"
"os"
"io"
"log"
"context"
"google.golang.org/grpc"
"github.com/p4gefau1t/trojan-go/api/service"
)
列出用户
此函数将列出所有用户信息,具体有:hash值、总流量、目前速度、限制速度、目前在线ip数、限制在线ip数。hash为密码的hash224加密。trojan仅靠密码识别用户。
func ListUsers(c service.TrojanServerServiceClient) {
stream, err := c.ListUsers(context.Background(), &service.ListUsersRequest{
})
if err != nil {
log.Printf("failed to call grpc command: $v", err)
}
for {
reply, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Printf("faild to recv: %v", err)
}
fmt.Println(reply)
break
}
}
获取用户
此函数跟上面的ListUsers不一样的地方在于:ListUsers函数会列出所有用户,GetUsers根据密码查询列出一个用户。
func GetUsers(c service.TrojanServerServiceClient, password string) {
stream, err := c.GetUsers(context.Background())
if err != nil {
log.Printf("faild to call: %v", err)
}
for {
stream.Send(&service.GetUsersRequest{
User: &service.User{
Password: password,
},
})
if err != nil {
log.Printf("failed to send: %v", err)
break
}
reply, err := stream.Recv()
if err != nil {
log.Printf("faild to recv: %v", err)
break
}
fmt.Println(reply)
break
}
}
增删用户
增删用户是动态的并且非永久,trojan-go停止后用户丢失,用来配合sspanel等前端面板。此函数一共有三种操作命令:Add、Delete和Modify,分别表示:增加用户、删除用户和修改用户。
func SetUsers(c service.TrojanServerServiceClient, operation, password string, traffic_total, speed_limit [2]uint64, ip_limit int32) {
stream, err := c.SetUsers(context.Background())
if err != nil {
log.Printf("faild to call: %v", err)
}
switch operation {
case "Add":
for {
stream.Send(&service.SetUsersRequest {
Operation: 0,
Status: &service.UserStatus {
User: &service.User{
Password: password,
},
},
})
if err != nil {
log.Printf("failed to send: %v", err)
break
}
reply, err := stream.Recv()
if err != nil {
log.Printf("faild to recv: %v", err)
break
}
fmt.Println(reply)
break
}
case "Delete":
for {
stream.Send(&service.SetUsersRequest {
Operation: 1,
Status: &service.UserStatus {
User: &service.User{
Password: password,
},
},
})
if err != nil {
log.Printf("failed to send: %v", err)
break
}
reply, err := stream.Recv()
if err != nil {
log.Printf("faild to recv: %v", err)
break
}
fmt.Println(reply)
break
}
case "Modify":
for {
stream.Send(&service.SetUsersRequest {
Operation: 2,
Status: &service.UserStatus {
User: &service.User{
Password: password,
},
TrafficTotal: &service.Traffic {
UploadTraffic: traffic_total[0],
DownloadTraffic: traffic_total[1],
},
SpeedLimit: &service.Speed {
UploadSpeed: speed_limit[0],
DownloadSpeed: speed_limit[1],
},
IpLimit: ip_limit,
},
})
if err != nil {
log.Printf("failed to send: %v", err)
break
}
reply, err := stream.Recv()
if err != nil {
log.Printf("faild to recv: %v", err)
break
}
fmt.Println(reply)
break
}
}
}
现在我们在main函数里调用上面函数实现功能就可以了。
func main() {
conn, err := grpc.Dial(":10000", grpc.WithInsecure())
if err != nil {
fmt.Printf("faild to connect: %v", err)
}
defer conn.Close()
hsClient := service.NewTrojanServerServiceClient(conn)
operation := "Modify"
password := "newpaw01"
traffic_total := [2]uint64 {8888, 8888}
speed_limit := [2]uint64 {10000, 10000}
var ip_limit int32 = 0
//ListUsers(hsClient)
//GetUsers(hsClient, password)
SetUsers(hsClient, operation, password ,traffic_total, speed_current, speed_limit, ip_current, ip_limit)
}
这里调用了SetUsers函数,修改密码为newpaw01的用户,将其总流量的上传流量和下载流量修改为8888字节,并将其限速10000字节,ip_limit为0表示不限制在线ip数。
开启api
代码是实现了,还需要trojan-go开启api。修改配置文件加入
"api": {
"enabled": true,
"api_addr": "127.0.0.1",
"api_port": 10000,
}
对接面板
对于sspanel面板。读取user表,查询所有enable为1、class大于等于节点node_class、node_group等于节点node_group(0则跳过)、transfer_enable大于u+d 的用户的uuid。uuid为trojan的密码,然后调用SetUsers增加这些密码为uuid的用户。当然在增加用户之前要判断是否已经存在该用户,有则跳过;已有用户无法找到则删除。
调用ListUsers将所有用户的总流量累加到ss_node表。
调用ListUsers将所有用户的在线ip数累加到ss_node_online_log表。
调用GetUsers 根据password等于uuid查询用户id、上传流量、下载流量、节点的比率、总流量插入user_traffic_log表。插入后调用SetUsers重置用户的总流量。
读取 /proc/uptime 和 /proc/laodavg 两个文件,把服务器运行时间和服务器1分钟、5分钟、10分钟进程数更新到ss_node_info表。
调用GetUsers 根据password等于uuid查询用户id插入alive_ip表。
这样一个对接sspanel面板的trojan后端就好了。可以实现的功能有:用户流量上报、用户在线ip数上报、节点在线状态上报、节点运行状态上报、节点总流量统计、分组功能。无法实现的功能:审计规则、禁用ip。
3 comments
对接面板程序有吗?
对接sspanel后端有吗?
对接sspanel面板的后端程序有吗?