Skip to content

Commit 53f3848

Browse files
committed
1.2.0 add SMTP and 5-second shield
1 parent 6231409 commit 53f3848

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1446
-606
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ language: go
33
sudo: false
44

55
go:
6-
- '1.14'
6+
- '1.15'
77

88
script:
99
- go build

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ https://doc.janusec.com/cn/
6666
* Debian 9/10+, CentOS/RHEL 7/8+, Debian 10+ is preferred (首选Debian 10+)
6767
* systemd
6868
* nftables
69-
* Golang 1.16+ (Required by Development Only, 仅开发环境需要)
69+
* Golang 1.15+ (Required by Development Only, 仅开发环境需要)
7070

7171
## Quick Start for Deployment (部署快速指引)
7272

backend/application.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func LoadApps() {
152152
RedirectHTTPS: dbApp.RedirectHTTPS,
153153
HSTSEnabled: dbApp.HSTSEnabled,
154154
WAFEnabled: dbApp.WAFEnabled,
155+
ShieldEnabled: dbApp.ShieldEnabled,
155156
ClientIPMethod: dbApp.ClientIPMethod,
156157
Description: dbApp.Description,
157158
Destinations: []*models.Destination{},
@@ -325,6 +326,7 @@ func UpdateApplication(param map[string]interface{}, clientIP string, authUser *
325326
redirectHTTPS := application["redirect_https"].(bool)
326327
hstsEnabled := application["hsts_enabled"].(bool)
327328
wafEnabled := application["waf_enabled"].(bool)
329+
shieldEnabled := application["shield_enabled"].(bool)
328330
ipMethod := models.IPMethod(application["ip_method"].(float64))
329331
var description string
330332
var ok bool
@@ -342,7 +344,7 @@ func UpdateApplication(param map[string]interface{}, clientIP string, authUser *
342344
var app *models.Application
343345
if appID == 0 {
344346
// new application
345-
newID := data.DAL.InsertApplication(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp)
347+
newID := data.DAL.InsertApplication(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, shieldEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp)
346348
app = &models.Application{
347349
ID: newID, Name: appName,
348350
InternalScheme: internalScheme,
@@ -352,6 +354,7 @@ func UpdateApplication(param map[string]interface{}, clientIP string, authUser *
352354
RedirectHTTPS: redirectHTTPS,
353355
HSTSEnabled: hstsEnabled,
354356
WAFEnabled: wafEnabled,
357+
ShieldEnabled: shieldEnabled,
355358
ClientIPMethod: ipMethod,
356359
Description: description,
357360
OAuthRequired: oauthRequired,
@@ -364,7 +367,7 @@ func UpdateApplication(param map[string]interface{}, clientIP string, authUser *
364367
} else {
365368
app, _ = GetApplicationByID(appID)
366369
if app != nil {
367-
err := data.DAL.UpdateApplication(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp, appID)
370+
err := data.DAL.UpdateApplication(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, shieldEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp, appID)
368371
if err != nil {
369372
utils.DebugPrintln("UpdateApplication", err)
370373
}
@@ -373,6 +376,7 @@ func UpdateApplication(param map[string]interface{}, clientIP string, authUser *
373376
app.RedirectHTTPS = redirectHTTPS
374377
app.HSTSEnabled = hstsEnabled
375378
app.WAFEnabled = wafEnabled
379+
app.ShieldEnabled = shieldEnabled
376380
app.ClientIPMethod = ipMethod
377381
app.Description = description
378382
app.OAuthRequired = oauthRequired

backend/certificate.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ func LoadCerts() {
4040
cert.CertContent = dbCert.CertContent
4141
pubCert := []byte(cert.CertContent)
4242
privKey, err := data.AES256Decrypt(dbCert.EncryptedPrivKey, false)
43-
utils.CheckError("LoadCerts AES256Decrypt", err)
43+
if err != nil {
44+
utils.DebugPrintln("LoadCerts AES256Decrypt", err)
45+
}
4446
tlsCert, err := tls.X509KeyPair(pubCert, privKey)
45-
utils.CheckError("LoadCerts X509KeyPair", err)
47+
if err != nil {
48+
utils.DebugPrintln("LoadCerts X509KeyPair", err)
49+
}
4650
cert.PrivKeyContent = string(privKey)
4751
cert.TlsCert = tlsCert
4852
cert.ExpireTime = dbCert.ExpireTime
@@ -156,8 +160,8 @@ func UpdateCertificate(param map[string]interface{}, clientIP string, authUser *
156160
}
157161
var certItem *models.CertItem
158162
tlsCert, err := tls.X509KeyPair([]byte(certContent), []byte(privKeyContent))
159-
utils.CheckError("UpdateCertificate X509KeyPair", err)
160163
if err != nil {
164+
utils.DebugPrintln("UpdateCertificate X509KeyPair", err)
161165
return nil, err
162166
}
163167
if id == 0 {

backend/init.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ func InitDatabase() {
121121
//if err != nil {
122122
//utils.DebugPrintln("InitDatabase ALTER TABLE ccpolicies ALTER COLUMN block_seconds", err)
123123
//}
124+
125+
// v1.2.0 add shield_enabled to application
126+
if !dal.ExistColumnInTable("applications", "shield_enabled") {
127+
// v1.2.0+ required
128+
err = dal.ExecSQL(`ALTER TABLE "applications" ADD COLUMN "shield_enabled" boolean default false`)
129+
if err != nil {
130+
utils.DebugPrintln("InitDatabase ALTER TABLE applications add shield_enabled", err)
131+
}
132+
}
124133
}
125134

126135
// LoadAppConfiguration ...

backend/node.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ func GetDBNodeIndex(nodeID int64) int {
7878
// DeleteNodeByID ...
7979
func DeleteNodeByID(id int64) error {
8080
dbNode, err := GetDBNodeByID(id)
81+
if err != nil {
82+
utils.DebugPrintln("DeleteNodeByID", err)
83+
return err
84+
}
8185
nodesMap.Delete(dbNode.LastIP)
82-
utils.CheckError("DeleteNodeByID", err)
8386
err = data.DAL.DeleteNodeByID(id)
8487
i := GetDBNodeIndex(id)
8588
dbNodes = append(dbNodes[:i], dbNodes[i+1:]...)

backend/rpc_application.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ func RPCSelectApplications() []*models.Application {
2020
rpcRequest := &models.RPCRequest{Action: "get_apps", Object: nil}
2121
resp, err := data.GetRPCResponse(rpcRequest)
2222
if err != nil {
23-
utils.CheckError("RPCSelectApplications GetResponse", err)
23+
utils.DebugPrintln("RPCSelectApplications GetResponse", err)
2424
return nil
2525
}
2626
rpcApps := &models.RPCApplications{}
2727
err = json.Unmarshal(resp, rpcApps)
2828
if err != nil {
29-
utils.CheckError("RPCSelectApplications Unmarshal", err)
29+
utils.DebugPrintln("RPCSelectApplications Unmarshal", err)
3030
return nil
3131
}
3232
applications := rpcApps.Object
@@ -38,13 +38,13 @@ func RPCSelectVipApplications() []*models.VipApp {
3838
rpcRequest := &models.RPCRequest{Action: "get_vip_apps", Object: nil}
3939
resp, err := data.GetRPCResponse(rpcRequest)
4040
if err != nil {
41-
utils.CheckError("RPCSelectVipApplications GetResponse", err)
41+
utils.DebugPrintln("RPCSelectVipApplications GetResponse", err)
4242
return nil
4343
}
4444
rpcVipApps := &models.RPCVipApps{}
4545
err = json.Unmarshal(resp, rpcVipApps)
4646
if err != nil {
47-
utils.CheckError("RPCSelectVipApplications Unmarshal", err)
47+
utils.DebugPrintln("RPCSelectVipApplications Unmarshal", err)
4848
return nil
4949
}
5050
vipApps := rpcVipApps.Object

backend/rpc_certificate.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,20 @@ func RPCSelectCertificates() []*models.CertItem {
2323
Action: "get_certs", Object: nil}
2424
resp, err := data.GetRPCResponse(rpcRequest)
2525
if err != nil {
26-
utils.CheckError("RPCSelectCertificates GetResponse", err)
26+
utils.DebugPrintln("RPCSelectCertificates GetResponse", err)
2727
return certs
2828
}
2929
rpcCertItems := &models.RPCCertItems{}
3030
if err = json.Unmarshal(resp, rpcCertItems); err != nil {
31-
utils.CheckError("RPCSelectCertificates Unmarshal", err)
31+
utils.DebugPrintln("RPCSelectCertificates Unmarshal", err)
3232
return certs
3333
}
3434
certItems := rpcCertItems.Object
3535
for _, certItem := range certItems {
3636
certItem.TlsCert, err = tls.X509KeyPair([]byte(certItem.CertContent), []byte(certItem.PrivKeyContent))
37-
utils.CheckError("RPCSelectCertificates X509KeyPair", err)
37+
if err != nil {
38+
utils.DebugPrintln("RPCSelectCertificates X509KeyPair", err)
39+
}
3840
certs = append(certs, certItem)
3941
}
4042
return certs

backend/rpc_domain.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ func RPCSelectDomains() (dbDomains []*models.DBDomain) {
2121
Action: "get_domains", Object: nil}
2222
resp, err := data.GetRPCResponse(rpcRequest)
2323
if err != nil {
24-
utils.CheckError("RPCSelectDomains GetResponse", err)
24+
utils.DebugPrintln("RPCSelectDomains GetResponse", err)
2525
return nil
2626
}
2727
rpcDBDomains := &models.RPCDBDomains{}
2828
err = json.Unmarshal(resp, rpcDBDomains)
2929
if err != nil {
30-
utils.CheckError("RPCSelectDomains Unmarshal", err)
30+
utils.DebugPrintln("RPCSelectDomains Unmarshal", err)
3131
return nil
3232
}
3333
dbDomains = rpcDBDomains.Object

backend/vip_app.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package backend
99

1010
import (
1111
"errors"
12-
"fmt"
1312
"hash/fnv"
1413
"io"
1514
"janusec/data"
@@ -117,6 +116,9 @@ func UDPForwarding(vipApp *models.VipApp, udpListenConn *net.UDPConn) {
117116
if err != nil {
118117
utils.DebugPrintln("UDPForwarding DialUDP could not connect to target", vipTarget.Destination, err)
119118
vipTarget.Online = false
119+
if data.NodeSetting.SMTP.SMTPEnabled {
120+
sendVIPOfflineNotification(vipApp, vipTarget.Destination)
121+
}
120122
break
121123
}
122124
if udpTargetConn == nil {
@@ -131,15 +133,18 @@ func UDPForwarding(vipApp *models.VipApp, udpListenConn *net.UDPConn) {
131133
udpTargetConn.SetDeadline(time.Now().Add(30 * time.Second))
132134
go func() {
133135
// make receiver ready before send request
134-
data := make([]byte, 2048)
136+
dataBuf := make([]byte, 2048)
135137
for {
136-
n, _, err := udpTargetConn.ReadFromUDP(data)
138+
n, _, err := udpTargetConn.ReadFromUDP(dataBuf)
137139
if err != nil {
138140
vipTarget.Online = false
141+
if data.NodeSetting.SMTP.SMTPEnabled {
142+
sendVIPOfflineNotification(vipApp, vipTarget.Destination)
143+
}
139144
break
140145
}
141146
// Response to client
142-
_, err = udpListenConn.WriteToUDP(data[:n], clientAddr)
147+
_, err = udpListenConn.WriteToUDP(dataBuf[:n], clientAddr)
143148
if err != nil {
144149
break
145150
}
@@ -179,6 +184,9 @@ func TCPForwarding(vipApp *models.VipApp, vipListener net.Listener) {
179184
if err != nil {
180185
utils.DebugPrintln("TCPForwarding could not connect to target", vipTarget.Destination, err)
181186
vipTarget.Online = false
187+
if data.NodeSetting.SMTP.SMTPEnabled {
188+
sendVIPOfflineNotification(vipApp, vipTarget.Destination)
189+
}
182190
continue
183191
}
184192
vipTarget.Online = true
@@ -297,7 +305,6 @@ func UpdateVipApp(param map[string]interface{}, clientIP string, authUser *model
297305
vipListener, err := net.Listen("tcp", ":"+strconv.FormatInt(vipApp.ListenPort, 10))
298306
if err != nil {
299307
utils.DebugPrintln("could not start server on port ", vipApp.ListenPort, err)
300-
fmt.Println("UpdateVipApp could not start server on port ", vipApp.ListenPort, vipListener, err)
301308
}
302309
if vipListener != nil {
303310
vipListener.Close()
@@ -385,3 +392,23 @@ func GetVipAppIndex(vipAppID int64) int {
385392
}
386393
return -1
387394
}
395+
396+
// sendVIPOfflineNotification ...
397+
func sendVIPOfflineNotification(app *models.VipApp, dest string) {
398+
var emails string
399+
if data.IsPrimary {
400+
emails = data.DAL.GetAppAdminAndOwnerEmails(app.Owner)
401+
} else {
402+
emails = data.NodeSetting.SMTP.AdminEmails
403+
}
404+
mailBody := "Backend virtual IP server: " + dest + " (" + app.Name + ") was offline."
405+
if len(mailBody) > 0 && len(emails) > 0 {
406+
go utils.SendEmail(data.NodeSetting.SMTP.SMTPServer,
407+
data.NodeSetting.SMTP.SMTPPort,
408+
data.NodeSetting.SMTP.SMTPAccount,
409+
data.NodeSetting.SMTP.SMTPPassword,
410+
emails,
411+
"[JANUSEC] Backend server offline notification",
412+
mailBody)
413+
}
414+
}

data/backend_application.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ import (
1414

1515
// CreateTableIfNotExistsApplications ...
1616
func (dal *MyDAL) CreateTableIfNotExistsApplications() error {
17-
const sqlCreateTableIfNotExistsApplications = `CREATE TABLE IF NOT EXISTS "applications"("id" bigserial PRIMARY KEY,"name" VARCHAR(128) NOT NULL,"internal_scheme" VARCHAR(8) NOT NULL,"redirect_https" boolean,"hsts_enabled" boolean,"waf_enabled" boolean,"ip_method" bigint,"description" VARCHAR(256) NOT NULL,"oauth_required" boolean,"session_seconds" bigint default 7200,"owner" VARCHAR(128) NOT NULL,"csp_enabled" boolean default false,"csp" VARCHAR(1024) NOT NULL DEFAULT 'default-src ''self''')`
17+
const sqlCreateTableIfNotExistsApplications = `CREATE TABLE IF NOT EXISTS "applications"("id" bigserial PRIMARY KEY,"name" VARCHAR(128) NOT NULL,"internal_scheme" VARCHAR(8) NOT NULL,"redirect_https" boolean,"hsts_enabled" boolean,"waf_enabled" boolean,"shield_enabled" boolean,"ip_method" bigint,"description" VARCHAR(256) NOT NULL,"oauth_required" boolean,"session_seconds" bigint default 7200,"owner" VARCHAR(128) NOT NULL,"csp_enabled" boolean default false,"csp" VARCHAR(1024) NOT NULL DEFAULT 'default-src ''self''')`
1818
_, err := dal.db.Exec(sqlCreateTableIfNotExistsApplications)
1919
return err
2020
}
2121

2222
// SelectApplications ...
2323
func (dal *MyDAL) SelectApplications() []*models.DBApplication {
24-
const sqlSelectApplications = `SELECT "id","name","internal_scheme","redirect_https","hsts_enabled","waf_enabled","ip_method","description","oauth_required","session_seconds","owner","csp_enabled","csp" FROM "applications"`
24+
const sqlSelectApplications = `SELECT "id","name","internal_scheme","redirect_https","hsts_enabled","waf_enabled","shield_enabled","ip_method","description","oauth_required","session_seconds","owner","csp_enabled","csp" FROM "applications"`
2525
rows, err := dal.db.Query(sqlSelectApplications)
26-
utils.CheckError("SelectApplications", err)
26+
if err != nil {
27+
utils.DebugPrintln("SelectApplications", err)
28+
return []*models.DBApplication{}
29+
}
2730
defer rows.Close()
2831
var dbApps []*models.DBApplication
2932
for rows.Next() {
@@ -35,6 +38,7 @@ func (dal *MyDAL) SelectApplications() []*models.DBApplication {
3538
&dbApp.RedirectHTTPS,
3639
&dbApp.HSTSEnabled,
3740
&dbApp.WAFEnabled,
41+
&dbApp.ShieldEnabled,
3842
&dbApp.ClientIPMethod,
3943
&dbApp.Description,
4044
&dbApp.OAuthRequired,
@@ -51,20 +55,24 @@ func (dal *MyDAL) SelectApplications() []*models.DBApplication {
5155
}
5256

5357
// InsertApplication insert an Application to DB
54-
func (dal *MyDAL) InsertApplication(appName string, internalScheme string, redirectHTTPS bool, hstsEnabled bool, wafEnabled bool, ipMethod models.IPMethod, description string, oauthRequired bool, sessionSeconds int64, owner string, cspEnabled bool, csp string) (newID int64) {
55-
const sqlInsertApplication = `INSERT INTO "applications"("name","internal_scheme","redirect_https","hsts_enabled","waf_enabled","ip_method","description","oauth_required","session_seconds","owner","csp_enabled","csp") VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) RETURNING "id"`
56-
err := dal.db.QueryRow(sqlInsertApplication, appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp).Scan(&newID)
57-
utils.CheckError("InsertApplication", err)
58+
func (dal *MyDAL) InsertApplication(appName string, internalScheme string, redirectHTTPS bool, hstsEnabled bool, wafEnabled bool, shieldEnabled bool, ipMethod models.IPMethod, description string, oauthRequired bool, sessionSeconds int64, owner string, cspEnabled bool, csp string) (newID int64) {
59+
const sqlInsertApplication = `INSERT INTO "applications"("name","internal_scheme","redirect_https","hsts_enabled","waf_enabled","shield_enabled","ip_method","description","oauth_required","session_seconds","owner","csp_enabled","csp") VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13) RETURNING "id"`
60+
err := dal.db.QueryRow(sqlInsertApplication, appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, shieldEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp).Scan(&newID)
61+
if err != nil {
62+
utils.DebugPrintln("InsertApplication", err)
63+
}
5864
return newID
5965
}
6066

6167
// UpdateApplication update an Application
62-
func (dal *MyDAL) UpdateApplication(appName string, internalScheme string, redirectHTTPS bool, hstsEnabled bool, wafEnabled bool, ipMethod models.IPMethod, description string, oauthRequired bool, sessionSeconds int64, owner string, cspEnabled bool, csp string, appID int64) error {
63-
const sqlUpdateApplication = `UPDATE "applications" SET "name"=$1,"internal_scheme"=$2,"redirect_https"=$3,"hsts_enabled"=$4,"waf_enabled"=$5,"ip_method"=$6,"description"=$7,"oauth_required"=$8,"session_seconds"=$9,"owner"=$10,"csp_enabled"=$11,"csp"=$12 WHERE "id"=$13`
68+
func (dal *MyDAL) UpdateApplication(appName string, internalScheme string, redirectHTTPS bool, hstsEnabled bool, wafEnabled bool, shieldEnabled bool, ipMethod models.IPMethod, description string, oauthRequired bool, sessionSeconds int64, owner string, cspEnabled bool, csp string, appID int64) error {
69+
const sqlUpdateApplication = `UPDATE "applications" SET "name"=$1,"internal_scheme"=$2,"redirect_https"=$3,"hsts_enabled"=$4,"waf_enabled"=$5,"shield_enabled"=$6,"ip_method"=$7,"description"=$8,"oauth_required"=$9,"session_seconds"=$10,"owner"=$11,"csp_enabled"=$12,"csp"=$13 WHERE "id"=$14`
6470
stmt, _ := dal.db.Prepare(sqlUpdateApplication)
6571
defer stmt.Close()
66-
_, err := stmt.Exec(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp, appID)
67-
utils.CheckError("UpdateApplication", err)
72+
_, err := stmt.Exec(appName, internalScheme, redirectHTTPS, hstsEnabled, wafEnabled, shieldEnabled, ipMethod, description, oauthRequired, sessionSeconds, owner, cspEnabled, csp, appID)
73+
if err != nil {
74+
utils.DebugPrintln("UpdateApplication", err)
75+
}
6876
return err
6977
}
7078

@@ -74,6 +82,8 @@ func (dal *MyDAL) DeleteApplication(appID int64) error {
7482
stmt, _ := dal.db.Prepare(sqlDeleteApplication)
7583
defer stmt.Close()
7684
_, err := stmt.Exec(appID)
77-
utils.CheckError("DeleteApplication", err)
85+
if err != nil {
86+
utils.DebugPrintln("DeleteApplication", err)
87+
}
7888
return err
7989
}

0 commit comments

Comments
 (0)