Skip to content

Commit c97ea37

Browse files
committed
Merge branch 'ssr'
2 parents 9715ea1 + fbe4f0c commit c97ea37

File tree

16 files changed

+468
-222
lines changed

16 files changed

+468
-222
lines changed

conf/config-temp.toml

-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ address = ":5000"
77
driver = "sqlite3"
88
connect = "./data/ignite.db"
99

10-
[ss]
11-
image = "goignite/ss-go:latest"
12-
1310
[host]
1411
address = "localhost"
1512
from = 5001

controllers/index.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (router *MainRouter) SignupHandler(c *gin.Context) {
6464
pwd := c.PostForm("password")
6565
confirmPwd := c.PostForm("confirm-password")
6666

67-
matched, _ := regexp.MatchString("^[a-zA-Z0-9]+$", username)
67+
matched, _ := regexp.MatchString("^[a-zA-Z0-9][a-zA-Z0-9_.-]+$", username)
6868

6969
if !matched {
7070
fmt.Println("Username is invalid!")

controllers/panel.go

+74-24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ import (
1111
"github.com/go-ignite/ignite/ss"
1212
)
1313

14+
var (
15+
servers = []string{"SS", "SSR"}
16+
ssMethods = []string{"aes-256-cfb", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305"}
17+
ssrMethods = []string{"aes-256-cfb", "aes-256-ctr", "chacha20", "chacha20-ietf"}
18+
serverMethodsMap = map[string]map[string]bool{}
19+
)
20+
21+
func init() {
22+
ssMethodMap := map[string]bool{}
23+
for _, method := range ssMethods {
24+
ssMethodMap[method] = true
25+
}
26+
ssrMethodMap := map[string]bool{}
27+
for _, method := range ssrMethods {
28+
ssrMethodMap[method] = true
29+
}
30+
31+
serverMethodsMap["SS"] = ssMethodMap
32+
serverMethodsMap["SSR"] = ssrMethodMap
33+
}
34+
1435
func (router *MainRouter) PanelIndexHandler(c *gin.Context) {
1536
userID, exists := c.Get("userId")
1637

@@ -32,16 +53,24 @@ func (router *MainRouter) PanelIndexHandler(c *gin.Context) {
3253
}
3354

3455
uInfo := &models.UserInfo{
35-
Id: user.Id,
36-
Host: ss.Host,
37-
Username: user.Username,
38-
Status: user.Status,
39-
PackageUsed: fmt.Sprintf("%.2f", user.PackageUsed),
40-
PackageLimit: user.PackageLimit,
41-
PackageLeft: fmt.Sprintf("%.2f", float32(user.PackageLimit)-user.PackageUsed),
42-
ServicePort: user.ServicePort,
43-
ServicePwd: user.ServicePwd,
44-
Expired: user.Expired.Format("2006-01-02"),
56+
Id: user.Id,
57+
Host: ss.Host,
58+
Username: user.Username,
59+
Status: user.Status,
60+
PackageUsed: fmt.Sprintf("%.2f", user.PackageUsed),
61+
PackageLimit: user.PackageLimit,
62+
PackageLeft: fmt.Sprintf("%.2f", float32(user.PackageLimit)-user.PackageUsed),
63+
ServicePort: user.ServicePort,
64+
ServicePwd: user.ServicePwd,
65+
ServiceMethod: user.ServiceMethod,
66+
ServiceType: user.ServiceType,
67+
Expired: user.Expired.Format("2006-01-02"),
68+
}
69+
if uInfo.ServiceMethod == "" {
70+
uInfo.ServiceMethod = "aes-256-cfb"
71+
}
72+
if uInfo.ServiceType == "" {
73+
uInfo.ServiceType = "SS"
4574
}
4675

4776
if user.PackageLimit == 0 {
@@ -51,7 +80,10 @@ func (router *MainRouter) PanelIndexHandler(c *gin.Context) {
5180
}
5281

5382
c.HTML(http.StatusOK, "panel.html", gin.H{
54-
"uInfo": uInfo,
83+
"uInfo": uInfo,
84+
"ss_methods": ssMethods,
85+
"ssr_methods": ssrMethods,
86+
"servers": servers,
5587
})
5688
}
5789

@@ -65,26 +97,43 @@ func (router *MainRouter) LogoutHandler(c *gin.Context) {
6597

6698
func (router *MainRouter) CreateServiceHandler(c *gin.Context) {
6799
userID, _ := c.Get("userId")
100+
method := c.PostForm("method")
101+
serverType := c.PostForm("server-type")
68102

69-
user := new(models.User)
70-
router.db.Id(userID).Get(user)
103+
fmt.Println("UserID", userID)
104+
fmt.Println("ServerType:", serverType)
105+
fmt.Println("Method:", method)
71106

72-
//Get all used ports.
73-
var usedPorts []int
74-
router.db.Table("user").Cols("service_port").Find(&usedPorts)
107+
methodMap, ok := serverMethodsMap[serverType]
108+
if !ok {
109+
resp := models.Response{Success: false, Message: "服务类型配置错误!"}
110+
c.JSON(http.StatusOK, resp)
111+
return
112+
}
75113

114+
if !methodMap[method] {
115+
resp := models.Response{Success: false, Message: "加密方法配置错误!"}
116+
c.JSON(http.StatusOK, resp)
117+
return
118+
}
119+
120+
user := new(models.User)
121+
router.db.Id(userID).Get(user)
76122
if user.ServiceId != "" {
77-
resp := models.Response{Success: false, Message: "Service already created!"}
123+
resp := models.Response{Success: false, Message: "服务已创建!"}
78124
c.JSON(http.StatusOK, resp)
79125
return
80126
}
81127

82-
// 1. Create ss service
83-
result, err := ss.CreateAndStartContainer(user.Username, &usedPorts)
128+
//Get all used ports.
129+
var usedPorts []int
130+
router.db.Table("user").Cols("service_port").Find(&usedPorts)
84131

132+
// 1. Create ss service
133+
result, err := ss.CreateAndStartContainer(serverType, user.Username, method, &usedPorts)
85134
if err != nil {
86135
log.Println("Create ss service error:", err.Error())
87-
resp := models.Response{Success: false, Message: "Create service error!"}
136+
resp := models.Response{Success: false, Message: "创建服务失败!"}
88137
c.JSON(http.StatusOK, resp)
89138
return
90139
}
@@ -94,8 +143,9 @@ func (router *MainRouter) CreateServiceHandler(c *gin.Context) {
94143
user.ServiceId = result.ID
95144
user.ServicePort = result.Port
96145
user.ServicePwd = result.Password
97-
affected, err := router.db.Id(userID).Cols("status", "service_port", "service_pwd", "service_id").Update(user)
98-
146+
user.ServiceMethod = method
147+
user.ServiceType = serverType
148+
affected, err := router.db.Id(userID).Cols("status", "service_port", "service_pwd", "service_id", "service_method", "service_type").Update(user)
99149
if affected == 0 || err != nil {
100150
if err != nil {
101151
log.Println("Update user info error:", err.Error())
@@ -104,14 +154,14 @@ func (router *MainRouter) CreateServiceHandler(c *gin.Context) {
104154
//Force remove created container
105155
ss.RemoveContainer(result.ID)
106156

107-
resp := models.Response{Success: false, Message: "Create service error!"}
157+
resp := models.Response{Success: false, Message: "更新用户信息失败!"}
108158
c.JSON(http.StatusOK, resp)
109159
return
110160
}
111161

112162
result.PackageLimit = user.PackageLimit
113163
result.Host = ss.Host
114-
resp := models.Response{Success: true, Message: "OK!", Data: result}
164+
resp := models.Response{Success: true, Message: "服务创建成功!", Data: result}
115165

116166
c.JSON(http.StatusOK, resp)
117167
}

controllers/router.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ type MainRouter struct {
1717

1818
func (self *MainRouter) Initialize(r *gin.Engine) {
1919
ss.Host = utils.HOST_Address
20-
ss.ImageUrl = utils.SS_Image
2120
ss.PortRange = []int{utils.HOST_From, utils.HOST_To}
2221

2322
//Init session store
@@ -39,8 +38,11 @@ func (self *MainRouter) Initialize(r *gin.Engine) {
3938
}
4039

4140
go func() {
42-
if err := ss.PullImage(); err != nil {
43-
log.Printf("Pull image [%s] error: %s\n", ss.ImageUrl, err.Error())
41+
if err := ss.PullImage(ss.SS_IMAGE); err != nil {
42+
log.Printf("Pull image [%s] error: %s\n", ss.SS_IMAGE, err.Error())
43+
}
44+
if err := ss.PullImage(ss.SSR_IMAGE); err != nil {
45+
log.Printf("Pull image [%s] error: %s\n", ss.SSR_IMAGE, err.Error())
4446
}
4547
}()
4648
self.router.Run(utils.APP_Address)

models/user.go

+4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ type User struct {
1111
PackageUsed float32 //Package bandwidth used, unit: GB
1212
Status int `xorm:"default 0"` // 0=>not created 1=>running 2=>stopped
1313
ServiceId string //SS container id
14+
ServiceType string //SS container type
1415
ServicePort int `xorm:"not null default 0"` //Docker service port for SS
1516
ServicePwd string //Password for SS
17+
ServiceMethod string //Encryption method for SS
1618
LastStatsResult uint64 //Last time stats result,unit: byte
1719
LastStatsTime *time.Time //Last time stats time
1820
Created time.Time `xorm:"created"`
@@ -31,5 +33,7 @@ type UserInfo struct {
3133
PackageLeftPercent string
3234
ServicePort int
3335
ServicePwd string
36+
ServiceMethod string
37+
ServiceType string
3438
Expired string
3539
}

ss/ss.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ import (
1313
"github.com/go-ignite/ignite/utils"
1414
)
1515

16+
const (
17+
SS_IMAGE = "goignite/ss-libev:latest"
18+
SSR_IMAGE = "goignite/ssr:latest"
19+
)
20+
1621
var (
17-
ImageUrl string
1822
client *docker.Client
1923
PortRange []int
2024
Host string
@@ -28,8 +32,17 @@ func init() {
2832
}
2933
}
3034

31-
func CreateContainer(name string, usedPorts *[]int) (*models.ServiceResult, error) {
32-
PullImage()
35+
func CreateContainer(serverType, name, method string, usedPorts *[]int) (*models.ServiceResult, error) {
36+
image := ""
37+
switch serverType {
38+
case "SS":
39+
image = SS_IMAGE
40+
case "SSR":
41+
image = SSR_IMAGE
42+
default:
43+
return nil, errors.New("invalid server type")
44+
}
45+
PullImage(image)
3346
password := utils.NewPasswd(16)
3447
port, err := getAvailablePort(usedPorts)
3548
if err != nil {
@@ -39,13 +52,14 @@ func CreateContainer(name string, usedPorts *[]int) (*models.ServiceResult, erro
3952
container, err := client.CreateContainer(docker.CreateContainerOptions{
4053
Name: name,
4154
Config: &docker.Config{
42-
Image: ImageUrl,
43-
Cmd: []string{"-k", password, "-p", portStr},
44-
ExposedPorts: map[docker.Port]struct{}{docker.Port(portStr + "/tcp"): {}},
55+
Image: image,
56+
Cmd: []string{"-k", password, "-m", method},
4557
},
4658
HostConfig: &docker.HostConfig{
4759
PortBindings: map[docker.Port][]docker.PortBinding{
48-
docker.Port(portStr + "/tcp"): {{HostPort: portStr}}},
60+
docker.Port("3389/tcp"): {{HostPort: portStr}},
61+
docker.Port("3389/udp"): {{HostPort: portStr}},
62+
},
4963
RestartPolicy: docker.AlwaysRestart(),
5064
},
5165
})
@@ -61,11 +75,11 @@ func CreateContainer(name string, usedPorts *[]int) (*models.ServiceResult, erro
6175
}
6276

6377
func StartContainer(id string) error {
64-
return client.StartContainer(id, nil)
78+
return client.StartContainer(id, &docker.HostConfig{})
6579
}
6680

67-
func PullImage() error {
68-
return client.PullImage(docker.PullImageOptions{Repository: ImageUrl, OutputStream: os.Stdout},
81+
func PullImage(image string) error {
82+
return client.PullImage(docker.PullImageOptions{Repository: image, OutputStream: os.Stdout},
6983
docker.AuthConfiguration{})
7084
}
7185

@@ -130,8 +144,8 @@ func GetContainerStatsOutNet(id string) (uint64, error) {
130144
return stats.Networks["eth0"].TxBytes, nil
131145
}
132146

133-
func CreateAndStartContainer(name string, usedPorts *[]int) (*models.ServiceResult, error) {
134-
r, err := CreateContainer(name, usedPorts)
147+
func CreateAndStartContainer(serverType, name, method string, usedPorts *[]int) (*models.ServiceResult, error) {
148+
r, err := CreateContainer(serverType, name, method, usedPorts)
135149
if err != nil {
136150
return nil, err
137151
}

static/css/dropdown.css

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
.big {
3+
font-size: 1.2em;
4+
}
5+
6+
.small {
7+
font-size: .7em;
8+
}
9+
10+
.square {
11+
width: .7em;
12+
height: .7em;
13+
margin: .5em;
14+
display: inline-block;
15+
}
16+
17+
/* Custom dropdown */
18+
.custom-dropdown {
19+
position: relative;
20+
display: inline-block;
21+
vertical-align: middle;
22+
margin: 10px; /* demo only */
23+
}
24+
25+
.custom-dropdown select {
26+
background-color: rgba(61, 201, 179, 1);
27+
color: #fff;
28+
font-size: inherit;
29+
padding: .5em;
30+
padding-right: 2.5em;
31+
width: 245px;
32+
border: 0;
33+
margin: 0;
34+
border-radius: 3px;
35+
text-indent: 0.01px;
36+
text-overflow: '';
37+
-webkit-appearance: button; /* hide default arrow in chrome OSX */
38+
}
39+
40+
.custom-dropdown::before,
41+
.custom-dropdown::after {
42+
content: "";
43+
position: absolute;
44+
pointer-events: none;
45+
}
46+
47+
.custom-dropdown::after { /* Custom dropdown arrow */
48+
content: "\25BC";
49+
height: 1em;
50+
font-size: .625em;
51+
line-height: 1;
52+
right: 1.2em;
53+
top: 50%;
54+
margin-top: -.5em;
55+
}
56+
57+
.custom-dropdown::before { /* Custom dropdown arrow cover */
58+
width: 2em;
59+
right: 0;
60+
top: 0;
61+
bottom: 0;
62+
border-radius: 0 3px 3px 0;
63+
}
64+
65+
.custom-dropdown select[disabled] {
66+
color: rgba(0,0,0,.3);
67+
}
68+
69+
.custom-dropdown select[disabled]::after {
70+
color: rgba(0,0,0,.1);
71+
}
72+
73+
.custom-dropdown::before {
74+
background-color: rgba(0,0,0,.15);
75+
}
76+
77+
.custom-dropdown::after {
78+
color: rgba(0,0,0,.4);
79+
}

0 commit comments

Comments
 (0)