Skip to content

Commit

Permalink
refactor: remove white list
Browse files Browse the repository at this point in the history
  • Loading branch information
go-bai committed Jul 27, 2023
1 parent 4c50b87 commit 0511ea9
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 125 deletions.
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ RUN go mod tidy && go build -ldflags "-s -w" -o main && upx -9 main

FROM scratch
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=builder /build/conf conf
COPY --from=builder /build/main /

ENTRYPOINT ["/main"]
30 changes: 5 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,19 @@ echo $TAG
docker run --rm --net=host --name http-proxy gobai/http-proxy:$TAG
```

### Test

if your local ip is 2.2.2.2 and your http-proxy server ip is 4.4.4.4

```bash
$ curl ip.sb
2.2.2.2
$ http_proxy=4.4.4.4:8888 curl ip.sb
4.4.4.4
```

### IP Whitelist

The ip whitelist file is located in `conf/whitelist`.

example:

```bash
127.0.0.1/32
1.1.1.1/32
```
### custom password

```bash
mkdir -p http-proxy-conf
echo '127.0.0.1/32' > http-proxy-conf/whitelist
docker run -d --net=host -e HTTP_PROXY_LISTEN_ADDR=":8888" -v ${PWD}/http-proxy-conf:/conf --restart always --name http-proxy gobai/http-proxy:$TAG
docker run -d --net=host -e HTTP_PROXY_PASS="xxx" --restart always --name http-proxy gobai/http-proxy:$TAG
```

## Environment Variable

| key | default |
| --- | - |
| `HTTP_PROXY_LISTEN_ADDR` | `:8888` |
| `HTTP_PROXY_ADDR` | `:38888` |
| `HTTP_PROXY_AUTH` | `on` |
| `HTTP_PROXY_PASS` | `` |

## Credits

Expand Down
Empty file removed conf/whitelist
Empty file.
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ module github.com/go-bai/http-proxy

go 1.20

require github.com/fsnotify/fsnotify v1.6.0

require golang.org/x/sys v0.4.0 // indirect
require github.com/google/uuid v1.3.0
7 changes: 2 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
150 changes: 59 additions & 91 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
package main

import (
"bufio"
"crypto/tls"
"fmt"
"encoding/base64"
"io"
"log"
"net"
"net/http"
"net/netip"
"os"
"strings"
"sync"
"time"

"github.com/fsnotify/fsnotify"
"github.com/google/uuid"
)

func handleTunneling(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -63,84 +61,25 @@ func copyHeader(dst, src http.Header) {
}
}

var (
whitelist sync.Map
whitelistName = "conf/whitelist"
whitelistPath = "conf"
)

func listenWhitelist() {
log.Printf("start watching %s...", whitelistName)
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Printf("watch %s failed: %s", whitelistName, err.Error())
func basicProxyAuth(proxyAuth string) (username, password string, ok bool) {
if proxyAuth == "" {
return
}
defer watcher.Close()
defer log.Printf("watcher closed!!!")

go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) && event.Name == whitelistName {
updateWhitelist()
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("watcher error:", err)
}
}
}()

err = watcher.Add(whitelistPath)
if err != nil {
log.Fatalf("watcher add %s failed: %s", whitelistName, err)
if !strings.HasPrefix(proxyAuth, "Basic ") {
return
}

<-make(chan struct{})
}

func updateWhitelist() {
log.Printf("start loading %s...", whitelistName)
defer log.Printf("%s has been loaded.", whitelistName)
f, err := os.Open(whitelistName)
c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(proxyAuth, "Basic "))
if err != nil {
log.Fatalf("open file %s failed: %s", whitelistName, err)
return
}
defer f.Close()

newWhitelist := make(map[string]struct{}, 0)

scanner := bufio.NewScanner(f)
for i := 0; scanner.Scan(); i++ {
line := strings.TrimSpace(scanner.Text())
ipPrefix, err := netip.ParsePrefix(line)
if err != nil {
log.Printf("line %d: \"%s\" parse failed: %s", i, line, err.Error())
}
newWhitelist[line] = struct{}{}
whitelist.Store(line, ipPrefix)
cs := string(c)
s := strings.IndexByte(cs, ':')
if s < 0 {
return
}

whitelist.Range(func(key, value any) bool {
if _, ok := newWhitelist[key.(string)]; !ok {
whitelist.Delete(key)
}
return true
})
}

func init() {

updateWhitelist()

go listenWhitelist()
return cs[:s], cs[s+1:], true
}

func handler(w http.ResponseWriter, r *http.Request) {
Expand All @@ -153,19 +92,19 @@ func handler(w http.ResponseWriter, r *http.Request) {

log.Printf("%-15s %-7s %s %s", addrPort.Addr(), r.Method, r.Host, r.URL.Path)

ok := true
whitelist.Range(func(k, v any) bool {
ok = !ok
if ok = v.(netip.Prefix).Contains(addrPort.Addr()); ok {
return false
if auth == authOn {
_, p, ok := basicProxyAuth(r.Header.Get("Proxy-Authorization"))
if !ok {
w.Header().Set("Proxy-Authenticate", `Basic realm=go`)
http.Error(w, "proxy auth required", http.StatusProxyAuthRequired)
return
}
return true
})

if !ok {
log.Printf("ip \"%s\" not configed in IPWhitelist", addrPort.Addr())
http.Error(w, fmt.Sprintf("ip \"%s\" not configed in IPWhitelist", addrPort.Addr()), http.StatusForbidden)
return
if p != pass {
http.Error(w, "proxy authentication failed", http.StatusForbidden)
return
}
r.Header.Del("Proxy-Authorization")
}

if r.Method == http.MethodConnect {
Expand All @@ -175,16 +114,45 @@ func handler(w http.ResponseWriter, r *http.Request) {
}
}

func main() {
httpProxyListenAddr := ":8888"
s, b := os.LookupEnv("HTTP_PROXY_LISTEN_ADDR")
var (
addr = ":38888"
auth = "on"
pass = ""
)

const (
authOn = "on"
authOff = "off"
)

func init() {
addrEnv, b := os.LookupEnv("HTTP_PROXY_ADDR")
if b {
addr = addrEnv
}
authEnv, b := os.LookupEnv("HTTP_PROXY_AUTH")
if b {
httpProxyListenAddr = s
auth = authEnv
}
if auth == authOn {
passEnv, b := os.LookupEnv("HTTP_PROXY_PASS")
if b {
pass = passEnv
} else {
pass = uuid.New().String()
}
}
}

func main() {
log.Printf("Listen on: %s\n", addr)
log.Printf("Auth: %s\n", auth)
if auth == authOn {
log.Printf("Password: %s\n", pass)
}

log.Printf("Listen on %s", httpProxyListenAddr)
server := &http.Server{
Addr: httpProxyListenAddr,
Addr: addr,
Handler: http.HandlerFunc(handler),
// Disable HTTP/2.
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
Expand Down

0 comments on commit 0511ea9

Please sign in to comment.