package proxy import ( "context" "net/http" "net/netip" "sneak.berlin/go/smallwebwaf/internal/lookup" ) // The headers in which the app is passed the client's AS number and // country while SWWAF_ADD_LOOKUP_HEADERS is set. Go sends a header name in // this form, so X-Client-ASN arrives as X-Client-Asn; header names are not // case-sensitive. const ( asnHeader = "X-Client-Asn" countryHeader = "X-Client-Country" ) // lookUp looks up the client's AS number and country, and notes them for // the log line, unless SWWAF_LOOKUP_SOURCE is off or the client is on a // private, loopback or link-local address, which no lookup can place. // While a setting needs the answer, a new client's request waits for it. // ctx is the request's own context. func (rq *request) lookUp(ctx context.Context) { if rq.h.config.LookupSource == "off" || !canBePlaced(rq.client) { return } answer := rq.h.geojs.LookUp(ctx, clientGroup(rq.client)) rq.lookedUp = true rq.line.ASN = answer.ASN rq.line.ASName = answer.ASName rq.line.Country = answer.Country } // addLookup adds answer, GeoJS's answer about a client, to the client's // history, and to the notes of the bans on its netblock that have no AS // number, AS name or country yet. func (h *handler) addLookup(answer lookup.Answer) { h.limiter.AddLookup(answer.Client, answer.Answered, answer.ASN, answer.ASName, answer.Country) h.ledger.AddLookup(h.netblock(answer.Client.Addr()), answer.ASN, answer.ASName, answer.Country) } // setLookupHeaders sets the headers in which the app is passed the // client's AS number and country, leaving out one that is unknown. Any // the client sent are removed, so that the app can believe them. func setLookupHeaders(header http.Header, asn, country string) { header.Del(asnHeader) header.Del(countryHeader) if asn != "" { header.Set(asnHeader, asn) } if country != "" { header.Set(countryHeader, country) } } // canBePlaced reports whether a lookup can place addr: private, loopback // and link-local addresses have no AS number or country. func canBePlaced(addr netip.Addr) bool { return !addr.IsPrivate() && !addr.IsLoopback() && !addr.IsLinkLocalUnicast() }