trojan-go是trojan的增强版,原版只是把流量套上了tls,trojan-go在此基础上增加了ws混淆方式,支持嵌套其他加密,据说trojan-go比原版优化的好,内存占用更少,速度更快。

客户端兼容问题:目前有的客户端还不trojan-go新特性,比如安卓客户端。好在两者参数兼容,只要去掉ws混淆和其他加密,trojan-go就可以当做trojan。

配置环境

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。

Last modification:January 4th, 2021 at 12:21 pm
如果觉得我的文章对你有用,请随意赞赏