golang http代理(带身份认证)
golang http代理(带身份认证) 直接上代码
配置文件: c.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ##配置文件 每行顶格写,分隔符冒号后面有空格 proxy_port: 9527 #监听端口 user: z1 #账号 <br>#若账号为空则无需认证 password: m1 #密码 ip_black_list : #要过滤的IP前缀 - '142.' - '35.' - '13.' domain_black_list : #要过滤的域名 - 'google.' #填写代理端口号,然后启动代理即可.注意端口号不要跟其他程序冲突 |
配置解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | package main import ( "fmt" "io/ioutil" "strings" "gopkg.in/yaml.v2" ) type yaml_Config struct { Listen string `yaml: "proxy_port" ` User string `yaml: "user" ` Password string `yaml: "password" ` StrSlice []string `yaml: "ip_black_list" ` StrSlice2 []string `yaml: "domain_black_list" ` } var conf yaml_Config //读取配置参数 conf func initconf() { data, err := ioutil.ReadFile( "c.yaml" ) if err != nil { fmt.Println(1, err) return } if err := yaml.Unmarshal([]byte(data), &conf); err != nil { //解析yaml文件 fmt.Println(2, err) return } fmt.Println( "proxy_port :" , conf.Listen) fmt.Println( "user :" , conf.User) fmt.Println( "password :" , conf.Password) fmt.Println( "ip_black_list is :" ) for i, m := range conf.StrSlice { fmt.Println(i, "==>" , m) } } /*黑名单*/ func veryip_black(s string) bool { if len(conf.StrSlice) != 0 { for _, ip := range conf.StrSlice { if strings.HasPrefix(s, ip) { return true } } } if len(conf.StrSlice2) != 0 { for _, domain := range conf.StrSlice2 { if strings.Contains(s, domain) { return true } } } return false } |
主文件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | /*重启标记*/ /* * @Author: wsh * @Date: 2022-05-21 11:08:32 * @Last Modified by: wsh * @Last Modified time: 2022-05-25 15:45:17 */ package main import ( "bufio" "bytes" "context" "encoding/base64" "fmt" "io" "io/ioutil" "log" "mylog" "net" "net/url" "os" "runtime" "strings" "time" ) var auth_string string var needAUTH bool func main() { initconf() proxyport := conf.Listen user := conf.User password := conf.Password if len(user) == 0 { fmt.Println( "用户名为空,无需认证客户端身份" ) needAUTH = false } else { needAUTH = true } auth_string = `Proxy-Authorization: Basic ` + base64.StdEncoding.EncodeToString([]byte(user+`:`+password)) fmt.Println( "正向代理服务端口号:" + proxyport) // tcp 连接,监听 端口 l, err := net.Listen( "tcp" , ":" +proxyport) if err != nil { log.Panic(err) } go func () { /*每x秒自动重启*/ x := 2 * 3600 for i := 0; i < x; i++ { fmt.Printf( "重启倒计时%v秒 \n" , x-i) time.Sleep(1 * time.Second) } _, fullFilename, _, _ := runtime.Caller(0) changeKey(fullFilename, ` /*重启标记*/ `, ` /*重启标记*/ `) }() // 接收请求并处理 for { client, err := l.Accept() if err != nil { mylog.Println(err) continue } //从chan 获取值 //是ctx的通道先返回的数据 go newFunction(client) // go handle(client) } } func newFunction(client net.Conn) { ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute) defer cancel() c := make( chan bool) add_temp := client.RemoteAddr() go func (client net.Conn) { handle(client) c <- true }(client) select { case <-c: //log.Println("执行完毕,退出本进程")/ return case <-ctx.Done(): mylog.Println(add_temp, "执行超时,退出本进程" ) return } } func handle(client net.Conn) { defer func () { if err := recover(); err != nil { mylog.Println( "捕获异常并恢复,异常是:" , err) } }() if client == nil { return } defer client.Close() // 用来存放客户端数据的缓冲区 var b [1024]byte //从客户端获取数据 n, err := client.Read(b[:]) if err != nil { mylog.Println(err) return } /*打印全部请求*/ //mylog.Println(string(b[:])) var method, URL, address string // 从客户端数据读入 method,url fmt.Sscanf(string(b[:bytes.IndexByte(b[:], '\n' )]), "%s%s" , &method, &URL) /*账号认证*/ b_temp := bytes.NewReader(b[:]) if needAUTH && !authC(b_temp) { mylog.Println(client.RemoteAddr(), "认证失败,账号密码错误" , string(b[:])) return } hostPortURL_temp, err := url.Parse(URL) if err != nil { hostPortURL_temp, err = url.Parse(` //` + URL) if err != nil { mylog.Println(`hostPortURL err`, err) return } } hostPortURL := hostPortURL_temp // 如果方法是 CONNECT,则为 https 协议 if method == "CONNECT" || hostPortURL.Opaque == "443" { address = hostPortURL.Scheme + ":" + hostPortURL.Opaque if veryip_black(hostPortURL.Scheme) { // log.Println("黑名单地址:", hostPortURL.Scheme) return } } else { //否则为 http 协议 address = hostPortURL.Host if veryip_black(address) { // log.Println("黑名单地址:", address) return } // 如果 host 不带端口,则默认为 80 if !strings.Contains(hostPortURL.Host, ":" ) { address = hostPortURL.Host + ":80" } } //获得了请求的 host 和 port,向服务端发起 tcp 连接 server, err := net.Dial( "tcp" , address) if err != nil { mylog.Println( "server err " , address, err) return } //如果使用 https 协议,需先向客户端表示连接建立完毕 if method == "CONNECT" || hostPortURL.Opaque == "443" { fmt.Fprint(client, "HTTP/1.1 200 Connection established\r\n\r\n" ) } else { //如果使用 http 协议,需将从客户端得到的 http 请求转发给服务端 server.Write(b[:n]) } //将客户端的请求转发至服务端,将服务端的响应转发给客户端。io.Copy 为阻塞函数,文件描述符不关闭就不停止 go io.Copy(server, client) io.Copy(client, server) } /*核对账号密码*/ func authC(b_temp *bytes.Reader) bool { buf := bufio.NewScanner(b_temp) for { if !buf.Scan() { break } line := strings.TrimSpace(buf.Text()) if strings.Contains(line, auth_string) { // mylog.Println("认证信息", line) return true } } return false } func changeKey(fileName string, str1 string, rstr1 string) { buf, _ := ioutil.ReadFile(fileName) //log.Printf("%v", string(buf)) if !bytes.Contains(buf, []byte(str1)) { return } fmt.Printf( "修改文件[%s]\n" , fileName) buf = bytes.ReplaceAll(buf, []byte(str1), []byte(rstr1)) ioutil.WriteFile(fileName, buf, os.ModePerm) } |
以上就是全部了.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!