Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
p4gefau1t committed Jun 26, 2020
2 parents 7feba10 + 81e79d9 commit df12fb0
Show file tree
Hide file tree
Showing 48 changed files with 1,061 additions and 473 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@ client.json
}
```

可以使用更简明易读的YAML语法进行配置,下面是一个客户端的例子,与上面的client.json等价

client.yaml

```yaml
run-type: client
local-addr: 127.0.0.1
local-port: 1080
remote-addr: www.your_awesome_domain_name.com
remote-port: 443
password:
- your_awesome_password
```

<a name="WebSocket"></a>

### WebSocket
Expand Down
18 changes: 10 additions & 8 deletions api/control/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,16 @@ func (o *apiController) setUsers(apiClient service.TrojanServerServiceClient) er
defer stream.CloseSend()

req := &service.SetUsersRequest{
User: &service.User{
Password: *o.password,
Hash: *o.hash,
},
IpLimit: int32(*o.ipLimit),
SpeedLimit: &service.Speed{
UploadSpeed: uint64(*o.uploadSpeedLimit),
DownloadSpeed: uint64(*o.downloadSpeedLimit),
Status: &service.UserStatus{
User: &service.User{
Password: *o.password,
Hash: *o.hash,
},
IpLimit: int32(*o.ipLimit),
SpeedLimit: &service.Speed{
UploadSpeed: uint64(*o.uploadSpeedLimit),
DownloadSpeed: uint64(*o.downloadSpeedLimit),
},
},
}
if *o.add {
Expand Down
226 changes: 85 additions & 141 deletions api/service/api.pb.go

Large diffs are not rendered by default.

15 changes: 5 additions & 10 deletions api/service/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ message Speed {

message User {
string password = 1;
string hash = 2; //optional
string hash = 2;
}

message UserStatus {
Expand Down Expand Up @@ -42,8 +42,7 @@ message ListUsersRequest {
}

message ListUsersResponse {
User user = 1;
UserStatus status = 2;
UserStatus status = 1;
}

message GetUsersRequest {
Expand All @@ -53,21 +52,17 @@ message GetUsersRequest {
message GetUsersResponse {
bool success = 1;
string info = 2;
User user = 3;
UserStatus status = 4;
UserStatus status = 3;
}

message SetUsersRequest {
User user = 1;
enum Operation {
Add = 0;
Delete = 1;
Modify = 2;
}
UserStatus status = 1;
Operation operation = 2;
Speed speed_limit = 3;
int32 ip_limit = 4;
Traffic traffic_total = 5;
}

message SetUsersResponse {
Expand All @@ -84,6 +79,6 @@ service TrojanServerService {
rpc ListUsers(ListUsersRequest) returns(stream ListUsersResponse){}
// obtain specified user's info
rpc GetUsers(stream GetUsersRequest) returns(stream GetUsersResponse){}
// setup exsisting users' config
// setup existing users' config
rpc SetUsers(stream SetUsersRequest) returns(stream SetUsersResponse){}
}
6 changes: 4 additions & 2 deletions api/service/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/p4gefau1t/trojan-go/log"
"github.com/p4gefau1t/trojan-go/statistic"
"github.com/p4gefau1t/trojan-go/tunnel/trojan"
"google.golang.org/grpc"
)

type ClientAPI struct {
Expand Down Expand Up @@ -58,7 +57,10 @@ func RunClientAPI(ctx context.Context, auth statistic.Authenticator) error {
if !cfg.API.Enabled {
return nil
}
server := grpc.NewServer()
server, err := newAPIServer(cfg)
if err != nil {
return err
}
service := &ClientAPI{
ctx: ctx,
auth: auth,
Expand Down
8 changes: 4 additions & 4 deletions api/service/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import "github.com/p4gefau1t/trojan-go/config"
const Name = "API_SERVICE"

type SSLConfig struct {
Enabled bool `json,yaml:"enabled"`
Enabled bool `json:"enabled" yaml:"enabled"`
CertPath string `json:"cert" yaml:"cert"`
KeyPath string `json:"key" yaml:"key"`
ClientAuth bool `json:"client_auth" yaml:"client-auth"`
VerifyClient bool `json:"verify_client" yaml:"verify-client"`
ClientCertPath []string `json:"client_cert" yaml:"client-cert"`
}

type APIConfig struct {
Enabled bool `json:"enabled" yaml:"enabled"`
APIHost string `json:"api_addr" yaml:"api-addr"`
APIPort int `json:"api_port" yaml:"api-port"`
SSL SSLConfig `json,yaml:"ssl"`
SSL SSLConfig `json:"ssl" yaml:"ssl"`
}

type Config struct {
API APIConfig `json,yaml:"api"`
API APIConfig `json:"api" yaml:"api"`
}

func init() {
Expand Down
97 changes: 73 additions & 24 deletions api/service/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package service

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"net"

"github.com/p4gefau1t/trojan-go/api"
Expand All @@ -13,6 +16,7 @@ import (
"github.com/p4gefau1t/trojan-go/statistic"
"github.com/p4gefau1t/trojan-go/tunnel/trojan"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

type ServerAPI struct {
Expand Down Expand Up @@ -40,7 +44,7 @@ func (s *ServerAPI) GetUsers(stream TrojanServerService_GetUsersServer) error {
if !valid {
stream.Send(&GetUsersResponse{
Success: false,
Info: "Invalid user: " + req.User.Hash,
Info: "invalid user: " + req.User.Hash,
})
continue
}
Expand Down Expand Up @@ -85,38 +89,46 @@ func (s *ServerAPI) SetUsers(stream TrojanServerService_SetUsersServer) error {
if err != nil {
return err
}
if req.User == nil {
return common.NewError("User is unspecified")
if req.Status == nil {
return common.NewError("status is unspecified")
}
if req.User.Hash == "" {
req.User.Hash = common.SHA224String(req.User.Password)
if req.Status.User.Hash == "" {
req.Status.User.Hash = common.SHA224String(req.Status.User.Password)
}
switch req.Operation {
case SetUsersRequest_Add:
err = s.auth.AddUser(req.User.Hash)
if req.SpeedLimit != nil {
valid, user := s.auth.AuthUser(req.User.Hash)
if err = s.auth.AddUser(req.Status.User.Hash); err != nil {
err = common.NewError("failed to add new user").Base(err)
break
}
if req.Status.SpeedLimit != nil {
valid, user := s.auth.AuthUser(req.Status.User.Hash)
if !valid {
return common.NewError("failed to add new user")
err = common.NewError("failed to auth new user").Base(err)
continue
}
if req.Status.SpeedLimit != nil {
user.SetSpeedLimit(int(req.Status.SpeedLimit.DownloadSpeed), int(req.Status.SpeedLimit.UploadSpeed))
}
if req.Status.TrafficTotal != nil {
user.SetTraffic(req.Status.TrafficTotal.DownloadTraffic, req.Status.TrafficTotal.UploadTraffic)
}
user.SetSpeedLimit(int(req.SpeedLimit.DownloadSpeed), int(req.SpeedLimit.UploadSpeed))
user.SetIPLimit(int(req.Status.IpLimit))
}
case SetUsersRequest_Delete:
err = s.auth.DelUser(req.User.Hash)
err = s.auth.DelUser(req.Status.User.Hash)
case SetUsersRequest_Modify:
valid, user := s.auth.AuthUser(req.User.Hash)
valid, user := s.auth.AuthUser(req.Status.User.Hash)
if !valid {
err = common.NewError("invalid user " + req.User.Hash)
err = common.NewError("invalid user " + req.Status.User.Hash)
} else {
if req.SpeedLimit.DownloadSpeed > 0 || req.SpeedLimit.UploadSpeed > 0 {
user.SetSpeedLimit(int(req.SpeedLimit.DownloadSpeed), int(req.SpeedLimit.UploadSpeed))
if req.Status.SpeedLimit != nil {
user.SetSpeedLimit(int(req.Status.SpeedLimit.DownloadSpeed), int(req.Status.SpeedLimit.UploadSpeed))
}
if req.IpLimit > 0 {
user.SetIPLimit(int(req.IpLimit))
}
if req.TrafficTotal.DownloadTraffic > 0 || req.TrafficTotal.UploadTraffic > 0 {
user.SetTraffic(req.TrafficTotal.DownloadTraffic, req.TrafficTotal.UploadTraffic)
if req.Status.TrafficTotal != nil {
user.SetTraffic(req.Status.TrafficTotal.DownloadTraffic, req.Status.TrafficTotal.UploadTraffic)
}
user.SetIPLimit(int(req.Status.IpLimit))
}
}
if err != nil {
Expand All @@ -142,10 +154,10 @@ func (s *ServerAPI) ListUsers(req *ListUsersRequest, stream TrojanServerService_
ipLimit := user.GetIPLimit()
ipCurrent := user.GetIP()
err := stream.Send(&ListUsersResponse{
User: &User{
Hash: user.Hash(),
},
Status: &UserStatus{
User: &User{
Hash: user.Hash(),
},
TrafficTotal: &Traffic{
DownloadTraffic: downloadTraffic,
UploadTraffic: uploadTraffic,
Expand All @@ -169,15 +181,52 @@ func (s *ServerAPI) ListUsers(req *ListUsersRequest, stream TrojanServerService_
return nil
}

func newAPIServer(cfg *Config) (*grpc.Server, error) {
var server *grpc.Server
if cfg.API.SSL.Enabled {
log.Info("api tls enabled")
keyPair, err := tls.LoadX509KeyPair(cfg.API.SSL.CertPath, cfg.API.SSL.KeyPath)
if err != nil {
return nil, common.NewError("failed to load key pair").Base(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{keyPair},
}
if cfg.API.SSL.VerifyClient {
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
tlsConfig.ClientCAs = x509.NewCertPool()
for _, path := range cfg.API.SSL.ClientCertPath {
log.Debug("loading client cert: " + path)
certBytes, err := ioutil.ReadFile(path)
if err != nil {
return nil, common.NewError("failed to load cert file").Base(err)
}
ok := tlsConfig.ClientCAs.AppendCertsFromPEM(certBytes)
if !ok {
return nil, common.NewError("fnvalid client cert")
}
}
}
creds := credentials.NewTLS(tlsConfig)
server = grpc.NewServer(grpc.Creds(creds))
} else {
server = grpc.NewServer()
}
return server, nil
}

func RunServerAPI(ctx context.Context, auth statistic.Authenticator) error {
cfg := config.FromContext(ctx, Name).(*Config)
if !cfg.API.Enabled {
return nil
}
server := grpc.NewServer()
service := &ServerAPI{
auth: auth,
}
server, err := newAPIServer(cfg)
if err != nil {
return err
}
RegisterTrojanServerServiceServer(server, service)
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cfg.API.APIHost, cfg.API.APIPort))
if err != nil {
Expand Down
38 changes: 22 additions & 16 deletions api/service/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ func TestServerAPI(t *testing.T) {
if err != nil {
break
}
fmt.Println(resp.User.Hash)
if resp.User.Hash != "hash1234" {
fmt.Println(resp.Status.User.Hash)
if resp.Status.User.Hash != "hash1234" {
t.Fail()
}
fmt.Println(resp.Status.SpeedCurrent)
Expand All @@ -70,8 +70,10 @@ func TestServerAPI(t *testing.T) {

stream3, err := server.SetUsers(ctx)
stream3.Send(&SetUsersRequest{
User: &User{
Hash: "hash1234",
Status: &UserStatus{
User: &User{
Hash: "hash1234",
},
},
Operation: SetUsersRequest_Delete,
})
Expand All @@ -84,8 +86,10 @@ func TestServerAPI(t *testing.T) {
t.Fail()
}
stream3.Send(&SetUsersRequest{
User: &User{
Hash: "newhash",
Status: &UserStatus{
User: &User{
Hash: "newhash",
},
},
Operation: SetUsersRequest_Add,
})
Expand All @@ -98,18 +102,20 @@ func TestServerAPI(t *testing.T) {
t.Fail()
}
stream3.Send(&SetUsersRequest{
User: &User{
Hash: "newhash",
Status: &UserStatus{
User: &User{
Hash: "newhash",
},
SpeedLimit: &Speed{
DownloadSpeed: 5000,
UploadSpeed: 3000,
},
TrafficTotal: &Traffic{
DownloadTraffic: 1,
UploadTraffic: 1,
},
},
Operation: SetUsersRequest_Modify,
SpeedLimit: &Speed{
DownloadSpeed: 5000,
UploadSpeed: 3000,
},
TrafficTotal: &Traffic{
DownloadTraffic: 1,
UploadTraffic: 1,
},
})
go func() {
for {
Expand Down
4 changes: 2 additions & 2 deletions constant/constant.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package constant

var (
Version = "VERSION"
Commit = "COMMIT"
Version = "Custom Version"
Commit = "Unknown Git Commit ID"
)
Loading

0 comments on commit df12fb0

Please sign in to comment.