事出有因,前俩天管理的一台云服务器有些异常,登录上去看了些有很多的ssh破解记录。当然我有自动防护和封地址的脚本在跑。但是只要端口开着肯定这样的请求肯定还是避免不了的。于是乎萌生了使用的时候打开防火墙,不使用的时候关闭的想法,因此老脑袋一拍用go撸了个小工具。通过http远程启动关闭需要的服务,执行命令之类的想法。我关了的主机比较多因此通过库配置命令,但是对于各位看官就不一定实用了,因此我又简单的改了下通过文件配置的。废话不多少走起。
简单的描述下,通过配置文件配置验证密钥,日志路径,已经执行命令的映射列表
{
"akey":"your'skey",
"logpath":"/var/log/httpcmd.log",
"cmdlist":{
"cmd1":"ipconfig",
"pingbd":"ping www.baidu.com",
"firewall-list":"firewall-cmd --list-all",
"open22": "firewall-cmd --permanent --add-port=22/tcp && firewall-cmd --reload",
"close22": "firewall-cmd --permanent --remove-port=22/tcp && firewall-cmd --reload",
}
}
就一个文件,简单的一百多行代码,编译不用多数了吧。
package main
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"github.com/google/logger"
"io/ioutil"
"net/http"
"os"
"os/exec"
"runtime"
"time"
)
var verbose = flag.Bool("verbose", false, "print info level logs to stdout")
var akey string
var cmdlist map[string]interface{}
var shell = false
func main() {
sysType := runtime.GOOS
jsonConfigFile := ""
if sysType == "linux" {
jsonConfigFile = "/etc/httpcmd.conf"
shell = true
}
if sysType == "windows" {
jsonConfigFile = "C:/httpcmd.conf"
}
tempMap := make(map[string]interface{})
content, err := ioutil.ReadFile(jsonConfigFile)
if err != nil {
panic(err)
}
err = json.Unmarshal(content, &tempMap)
akey = tempMap["akey"].(string)
logPath := tempMap["logpath"].(string)
cmdlist = tempMap["cmdlist"].(map[string]interface{})
//for k, v := range cmdlist {
//fmt.Println("============", k, "==================")
////responseBody := RunCmd()
////fmt.Println(responseBody)
//command := v.(string)
//responseBody := RunCmd(command, shell)
//fmt.Println(responseBody)
//}
lf, err := os.OpenFile(logPath, os.O_CREATE | os.O_WRONLY | os.O_APPEND, 0660)
if err != nil {
logger.Fatalf("Failed to open log file: %v", err)
}
defer lf.Close()
defer logger.Init("LoggerExample", *verbose, true, lf).Close()
http.HandleFunc("/httpcmd", httpCmd)
//设置监听的端口
errs := http.ListenAndServe(":10000", nil)
if errs != nil {
logger.Info("start error :", errs)
}
logger.Info("service is started")
}
func md5V(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}
func httpCmd(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
key := r.Form.Get("key")
item := r.Form.Get("item")
timeStr:=time.Now().Format("2006010215")
fmt.Println(timeStr)
responseBody := "Invalid request"
//通过简单的md5校验实现简单层面的安全控制
if key == md5V(akey+":"+timeStr+":"+item) {
if realCmd, ok := cmdlist[item]; ok {
command := realCmd.(string)
responseBody = RunCmd(command, shell)
}
}
fmt.Fprintln(w, responseBody)
}
func RunCmd(cmd string, shell bool) string {
logger.Info("cmd=> ",cmd)
if shell {
out, err := exec.Command("bash", "-c", cmd).Output()
if err != nil {
logger.Info("InvalidCmd=> ",cmd)
//panic("some error found")
}
return string(out)
} else {
out, err := exec.Command("cmd", "/C", cmd).Output()
if err != nil {
logger.Info("InvalidCmd=> ",cmd)
//panic("some error found")
}
return string(out)
}
}
编译完后启动服务,并通过nginx映射的一个别人想不到的路径上。
location /xxxpath {
proxy_pass http://localhost:10000/;
}
此处我写了python脚本可以实用
# coding:utf-8
import time
import sys
import requests
from bs4 import BeautifulSoup
import hashlib
import time
headers = {"Accept": "text/html,application/xhtml+xml,application/xml;",
"Accept-Encoding": "gzip",
"Accept-Language": "zh-CN,zh;q=0.8",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) "
}
def md5str(*args):
datastr = ""
for x in args:
datastr = datastr + str(x)
m = hashlib.md5(datastr.encode(encoding='utf-8'))
return m.hexdigest()
if __name__ == "__main__":
pagecount = 0
times = time.strftime('%Y%m%d%H', time.localtime(time.time()))
qh_search = "http://xadress/nixiangbudao/httpcmd"
cmd = sys.argv[1]
akey = "meiyoumima"
key = md5str(akey+":"+times+":"+cmd)
data = {'item':cmd,'key':key}
r = requests.post(qh_search, headers=headers,data=data)
if r.status_code == 200:
print(r.text)
else:
print("request error code ", r.status_code)
# 打开22端口
python3 httpcmd.py open22
# 关闭22端口
python3 httpcmd.py close22