Skip to content

Commit

Permalink
detect client address behind proxy (closes #9)
Browse files Browse the repository at this point in the history
  • Loading branch information
reddec committed Jan 1, 2023
1 parent f65a28e commit 34109d5
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
2 changes: 2 additions & 0 deletions cmd/trusted-cgi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Config struct {
DisableChroot bool `long:"disable-chroot" env:"DISABLE_CHROOT" description:"Disable use different user for spawn"`
SSHKey string `long:"ssh-key" env:"SSH_KEY" description:"Path to ssh key. If not empty and not exists - it will be generated" default:".id_rsa"`
Dev bool `long:"dev" env:"DEV" description:"Enabled dev mode (disables chroot)"`
BehindProxy bool `long:"behind-proxy" env:"BEHIND_PROXY" description:"Respect X-Real-Ip and X-Forwarded-For"`
StatsCache uint `long:"stats-cache" env:"STATS_CACHE" description:"Maximum cache for stats" default:"8192"`
StatsFile string `long:"stats-file" env:"STATS_FILE" description:"Binary file for statistics dump" default:".stats"`
StatsInterval time.Duration `long:"stats-interval" env:"STATS_INTERVAL" description:"Interval for dumping stats to file" default:"30s"`
Expand Down Expand Up @@ -185,6 +186,7 @@ func run(ctx context.Context, config Config) error {
Cases: useCases,
Queues: queueManager,
Dev: config.Dev,
BehindProxy: config.BehindProxy,
Tracker: tracker,
TokenHandler: userApi,
ProjectAPI: projectApi,
Expand Down
7 changes: 7 additions & 0 deletions docs/administrating/policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,10 @@ instead of real address.
Should be defined in default notation `XXX.YYY.ZZZ.TTT`, IPv6 has to be supported but not tested.

The performance almost not impacted regardless number of IP.

Since `0.3.8` the following headers are respected if `--behind-proxy` (`BEHIND_PROXY=true`) flag is set:

- `X-Real-Ip`
- `X-Forwarded-For`

The first address in chain will be used as client address.
3 changes: 2 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Server struct {
Cases application.Cases
Queues application.Queues
Dev bool
BehindProxy bool
Tracker stats.Recorder
TokenHandler TokenHandler
ProjectAPI api.ProjectAPI
Expand Down Expand Up @@ -137,7 +138,7 @@ func (srv *Server) withRequest(ctx context.Context, next resourceHandler) http.H
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
sections := strings.SplitN(strings.Trim(request.URL.Path, "/"), "/", 2)
uid := sections[0]
req := types.FromHTTP(request)
req := types.FromHTTP(request, srv.BehindProxy)
var record = stats.Record{
UID: uid,
Request: *req,
Expand Down
26 changes: 24 additions & 2 deletions types/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package types
import (
"io"
"net/http"
"strings"
)

//go:generate msgp
Expand All @@ -17,7 +18,7 @@ type Request struct {
}

// Create request from HTTP request
func FromHTTP(r *http.Request) *Request {
func FromHTTP(r *http.Request, behindProxy bool) *Request {
_ = r.ParseForm()
var vals = make(map[string]string)
for k, v := range r.Form {
Expand All @@ -27,11 +28,17 @@ func FromHTTP(r *http.Request) *Request {
for k, v := range r.Header {
headers[k] = v[0]
}
var address string
if behindProxy {
address = getRequestAddress(r)
} else {
address = r.RemoteAddr
}
return &Request{
Method: r.Method,
URL: r.RequestURI,
Path: r.URL.Path,
RemoteAddress: r.RemoteAddr,
RemoteAddress: address,
Form: vals,
Headers: headers,
Body: r.Body,
Expand All @@ -47,3 +54,18 @@ func (z *Request) WithBody(reader io.ReadCloser) *Request {
cp.Body = reader
return &cp
}

func getRequestAddress(r *http.Request) string {
address := getFirstHeader(r, r.RemoteAddr, "X-Real-Ip", "X-Forwarded-For")
address = strings.TrimSpace(strings.SplitN(address, ",", 2)[0])
return address
}

func getFirstHeader(r *http.Request, defaultValue string, headers ...string) string {
for _, h := range headers {
if v := r.Header.Get(h); v != "" {
return v
}
}
return defaultValue
}

0 comments on commit 34109d5

Please sign in to comment.