Cảnh báo đăng nhập bằng Golang
Dạo gần đây mình đang theo học một môn võ công mới. Môn võ công này kinh dị đến nỗi mới theo được vài ngày đã bị tàu hỏa nhập ma. Cấu trúc thì xấu kinh dị, thuật ngữ thì khó, Nhưng cuộc sống mà không có gì là tươi đẹp. Cuộc đời xô đẩy dẫn đến mình phải luyện nó thôi. Golang hay còn gọi là Go ...
Dạo gần đây mình đang theo học một môn võ công mới. Môn võ công này kinh dị đến nỗi mới theo được vài ngày đã bị tàu hỏa nhập ma. Cấu trúc thì xấu kinh dị, thuật ngữ thì khó, Nhưng cuộc sống mà không có gì là tươi đẹp. Cuộc đời xô đẩy dẫn đến mình phải luyện nó thôi.
Golang hay còn gọi là Go được ông anh gồ phát triển vào năm 2007 sau đó được công bố vào năm 2009. Với tốc độ thực thi mã lệnh cực nhanh và xử lý các tác vụ hoàn hảo, không gì tuyệt vời hơn nếu sử dụng nó để làm 1 vài Microservices bằng Go
Ý tưởng: Khi người dùng đăng nhập hệ thống linux, Server sẽ tự call đến 1 service, Service này có nhiệm vụ gửi 1 thông điệp notification đến các kênh thông báo như SMS, email, slack, chatwork, vv...
Xây dựng Lên kế hoạch thôi Hãy chắc chắn rằng linux của bạn đã install go B1. tạo file config.json
{ "SMTP_EMAIL": "", "SMTP_PASSWORD": "", "SMTP_SERVER": "", "SMTP_PORT": 25, "SLACK_WEBHOOK": "token", "CHATWORK_TOKEN": "token", "ROOM_ID": "room_id", "LISTEN": ":8000" }
Ở đây mình sẽ ví dụ gửi đến 2 kênh thông báo slack và chatwork
B2. Xây dựng go notification.go
Để Notification tới chatwork chắc chắn các bạn phải sử dụng đến api chatwork rồi api chatwork. Hãy tạo 1 em boot sau đó request lấy api token nhét vào config.jon là ok rồi
Import thư viện cần thiết
import ( "encoding/json" "fmt" "io/ioutil" "net/http" )
struct lưu trữ thông tin cấu hình
type Config struct { SMTP_EMAIL string SMTP_PASSWORD string SMTP_SERVER string SMTP_PORT int SLACK_WEBHOOK string CHATWORK_TOKEN string ROOM_ID string LISTEN string }
Đọc file từ config.jon và nạp vào struct Config
func loadConfig() *Config { conf := Config{} content, e := ioutil.ReadFile("./config.json") checkErr(e) err := json.Unmarshal(content, &conf) checkErr(err) return &conf }
checkErr() Method này dùng để check lỗi chương trình
Send notification tới chatwork
func doSendChatwork(body string) []byte { client := &http.Client{} req, requestErr := http.NewRequest("POST", "https://api.chatwork.com/v2/rooms/"+config.ROOM_ID+"/messages?body="+body, nil) checkErr(requestErr) req.Header.Add("X-ChatWorkToken", config.CHATWORK_TOKEN) resp, responseErr := client.Do(req) checkErr(responseErr) return parseBody(resp) }
Method thực thi
func notifyLogin(w http.ResponseWriter, r *http.Request) { response := doSendChatwork("Warning%21%20Logged") fmt.Println(response) }
Hàm main chính
func main() { config = loadConfig() http.HandleFunc("/notify/login", notifyLogin) err := http.ListenAndServe(config.LISTEN, nil) checkErr(err) }
Service tự tạo 1 webserver chạy ở port trong config. Để build thành file scripts trên linux sử dụng với lệnh sau
$ go build notification.go
Run scripts $ ./notification
Tạo Trigger trên các server Agent
Khi người dùng đăng nhập vào hệ thống các scripts trong /etc/profile.d/ sẽ được thực thi. Lợi dụng điều này ta sẽ tạo 1 scripts với nội dung như sau
#!/usr/bin/env bash if [ -n "$SSH_CLIENT" ];then LOGIN_NOTIFY_HOST="localhost:8000" REMOTE_IP=`echo $SSH_CLIENT|awk '{print $1}'` LOGIN_NOTIFY_API="http://${LOGIN_NOTIFY_HOST}/notify/login?user=${USER}&remoteip=$REMOTE_IP" /usr/bin/curl "$LOGIN_NOTIFY_API" &> /dev/null fi
Scripts sẽ call đến service kèm theo thông tin User và địa chỉ IP đăng nhập. Ngay lập tức services sẽ gửi 1 thông điệp tới chatwork "Attacked by xxx"
Toàn bộ source code được lưu tại https://github.com/dung13890/go-notification