mirror of
https://github.com/dcarrillo/whatismyip.git
synced 2024-12-22 00:28:00 +00:00
Add experimental support for HTTP/3 (#8)
* Wait for service in integration tests instead of watching for a string * Add http3 experimental support
This commit is contained in:
parent
de78dcdf52
commit
19c72f94a5
7
.github/workflows/codeql-analysis.yml
vendored
7
.github/workflows/codeql-analysis.yml
vendored
@ -36,7 +36,12 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: install go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: true
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
|
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
@ -37,6 +37,11 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: install go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: true
|
||||
|
||||
- name: Set env
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
39
README.md
39
README.md
@ -7,18 +7,19 @@
|
||||
[![License Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE)
|
||||
|
||||
- [What is my IP address](#what-is-my-ip-address)
|
||||
- [Features](#features)
|
||||
- [Endpoints](#endpoints)
|
||||
- [Build](#build)
|
||||
- [Usage](#usage)
|
||||
- [Examples](#examples)
|
||||
- [Run a default TCP server](#run-a-default-tcp-server)
|
||||
- [Run a TLS (HTTP/2) server only](#run-a-tls-http2-server-only)
|
||||
- [Run a default TCP server with a custom template and trust a pair of custom headers set by an upstream proxy](#run-a-default-tcp-server-with-a-custom-template-and-trust-a-pair-of-custom-headers-set-by-an-upstream-proxy)
|
||||
- [Download](#download)
|
||||
- [Docker](#docker)
|
||||
- [Run a container locally using test databases](#run-a-container-locally-using-test-databases)
|
||||
- [From Docker Hub](#from-docker-hub)
|
||||
- [Features](#features)
|
||||
- [Endpoints](#endpoints)
|
||||
- [Build](#build)
|
||||
- [Usage](#usage)
|
||||
- [Examples](#examples)
|
||||
- [Run a default TCP server](#run-a-default-tcp-server)
|
||||
- [Run a TLS (HTTP/2) server only](#run-a-tls-http2-server-only)
|
||||
- [Run an HTTP/3 server](#run-an-http3-server)
|
||||
- [Run a default TCP server with a custom template and trust a pair of custom headers set by an upstream proxy](#run-a-default-tcp-server-with-a-custom-template-and-trust-a-pair-of-custom-headers-set-by-an-upstream-proxy)
|
||||
- [Download](#download)
|
||||
- [Docker](#docker)
|
||||
- [Run a container locally using test databases](#run-a-container-locally-using-test-databases)
|
||||
- [From Docker Hub](#from-docker-hub)
|
||||
|
||||
Just another "what is my IP address" service, including geolocation and headers information, written in go with high performance in mind, it uses [gin](https://github.com/gin-gonic/gin) which uses [httprouter](https://github.com/julienschmidt/httprouter) a lightweight high performance HTTP multiplexer.
|
||||
|
||||
@ -37,6 +38,7 @@ curl -6 ifconfig.es
|
||||
## Features
|
||||
|
||||
- TLS and HTTP/2.
|
||||
- Experimental support to HTTP/3. HTTP/3 requires a TLS server running (`-tls-bind`), as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.
|
||||
- Can run behind a proxy by trusting a custom header (usually `X-Real-IP`) to figure out the source IP address. It also supports a custom header to resolve the client port, if the proxy can only add a header for the IP (for example a fixed header from CDNs) the client port is shown as unknown.
|
||||
- IPv4 and IPv6.
|
||||
- Geolocation info including ASN. This feature is possible thanks to [maxmind](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en) GeoLite2 databases. In order to use these databases, a license key is needed. Please visit Maxmind site for further instructions and get a free license.
|
||||
@ -67,7 +69,7 @@ curl -6 ifconfig.es
|
||||
|
||||
## Build
|
||||
|
||||
Golang >= 1.17 is required. Previous versions may work.
|
||||
Golang >= 1.19 is required.
|
||||
|
||||
`make build`
|
||||
|
||||
@ -77,6 +79,8 @@ Golang >= 1.17 is required. Previous versions may work.
|
||||
Usage of whatismyip:
|
||||
-bind string
|
||||
Listening address (see https://pkg.go.dev/net?#Listen) (default ":8080")
|
||||
-enable-http3
|
||||
Enable HTTP/3 protocol. HTTP/3 requires --tls-bind set, as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.
|
||||
-enable-secure-headers
|
||||
Add sane security-related headers to every response
|
||||
-geoip2-asn string
|
||||
@ -114,6 +118,13 @@ Usage of whatismyip:
|
||||
-bind "" -tls-bind :8081 -tls-crt ./test/server.pem -tls-key ./test/server.key
|
||||
```
|
||||
|
||||
### Run an HTTP/3 server
|
||||
|
||||
```bash
|
||||
./whatismyip -geoip2-city ./test/GeoIP2-City-Test.mmdb -geoip2-asn ./test/GeoLite2-ASN-Test.mmdb \
|
||||
-bind "" -tls-bind :8081 -tls-crt ./test/server.pem -tls-key ./test/server.key -enable-http3
|
||||
```
|
||||
|
||||
### Run a default TCP server with a custom template and trust a pair of custom headers set by an upstream proxy
|
||||
|
||||
```bash
|
||||
@ -127,7 +138,7 @@ Download latest version from https://github.com/dcarrillo/whatismyip/releases
|
||||
|
||||
## Docker
|
||||
|
||||
An ultra-light (~10MB) image is available at [docker hub](https://hub.docker.com/r/dcarrillo/whatismyip).
|
||||
An ultra-light (~12MB) image is available at [docker hub](https://hub.docker.com/r/dcarrillo/whatismyip).
|
||||
|
||||
### Run a container locally using test databases
|
||||
|
||||
|
@ -17,13 +17,14 @@ import (
|
||||
|
||||
"github.com/dcarrillo/whatismyip/models"
|
||||
"github.com/dcarrillo/whatismyip/router"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
http3 "github.com/quic-go/quic-go/http3"
|
||||
)
|
||||
|
||||
var (
|
||||
tcpServer *http.Server
|
||||
tlsServer *http.Server
|
||||
h3Server *http3.Server
|
||||
engine *gin.Engine
|
||||
)
|
||||
|
||||
@ -48,6 +49,9 @@ func main() {
|
||||
|
||||
if setting.App.TLSAddress != "" {
|
||||
runTLSServer()
|
||||
if setting.App.EnableHTTP3 {
|
||||
runQuicServer()
|
||||
}
|
||||
}
|
||||
|
||||
runHandler()
|
||||
@ -74,10 +78,20 @@ func runHandler() {
|
||||
runTCPServer()
|
||||
}
|
||||
if setting.App.TLSAddress != "" {
|
||||
if setting.App.EnableHTTP3 {
|
||||
if err := h3Server.Close(); err != nil {
|
||||
log.Printf("QUIC server forced to shutdown")
|
||||
}
|
||||
}
|
||||
|
||||
if err := tlsServer.Shutdown(ctx); err != nil {
|
||||
log.Printf("TLS server forced to shutdown: %s", err)
|
||||
}
|
||||
runTLSServer()
|
||||
|
||||
if setting.App.EnableHTTP3 {
|
||||
runQuicServer()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("Shutting down...")
|
||||
@ -87,6 +101,11 @@ func runHandler() {
|
||||
}
|
||||
}
|
||||
if setting.App.TLSAddress != "" {
|
||||
if setting.App.EnableHTTP3 {
|
||||
if err := h3Server.Close(); err != nil {
|
||||
log.Printf("QUIC server forced to shutdown: %s", err)
|
||||
}
|
||||
}
|
||||
if err := tlsServer.Shutdown(ctx); err != nil {
|
||||
log.Printf("TLS server forced to shutdown: %s", err)
|
||||
}
|
||||
@ -132,6 +151,31 @@ func runTLSServer() {
|
||||
}()
|
||||
}
|
||||
|
||||
func runQuicServer() {
|
||||
h3Server = &http3.Server{
|
||||
Addr: setting.App.TLSAddress,
|
||||
Handler: tlsServer.Handler,
|
||||
}
|
||||
|
||||
previousHandler := tlsServer.Handler
|
||||
tlsServer.Handler = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if err := h3Server.SetQuicHeaders(rw.Header()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
previousHandler.ServeHTTP(rw, req)
|
||||
})
|
||||
|
||||
go func() {
|
||||
log.Printf("Starting QUIC server listening on %s (udp)", setting.App.TLSAddress)
|
||||
if err := h3Server.ListenAndServeTLS(setting.App.TLSCrtPath, setting.App.TLSKeyPath); err != nil &&
|
||||
err.Error() != "quic: Server closed" {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Stopping QUIC server...")
|
||||
}()
|
||||
}
|
||||
|
||||
func setupEngine() {
|
||||
gin.DisableConsoleColor()
|
||||
if os.Getenv(gin.EnvGinMode) == "" {
|
||||
|
11
go.mod
11
go.mod
@ -6,6 +6,7 @@ require (
|
||||
github.com/gin-contrib/secure v0.0.1
|
||||
github.com/gin-gonic/gin v1.9.0
|
||||
github.com/oschwald/maxminddb-golang v1.10.0
|
||||
github.com/quic-go/quic-go v0.33.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/testcontainers/testcontainers-go v0.13.0
|
||||
)
|
||||
@ -28,10 +29,13 @@ require (
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/goccy/go-json v0.10.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
@ -44,21 +48,28 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
||||
github.com/opencontainers/runc v1.1.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220810155839-1856144b1d9c // indirect
|
||||
google.golang.org/grpc v1.48.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
|
33
go.sum
33
go.sum
@ -94,8 +94,6 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.8.3 h1:pf6fGl5eqWYKkx1RcD4qpuX+BIUaduv/wTm5ekWJ80M=
|
||||
github.com/bytedance/sonic v1.8.3/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.8.5 h1:kjX0/vo5acEQ/sinD/18SkA/lDDUk23F0RcaHvI7omc=
|
||||
github.com/bytedance/sonic v1.8.5/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
@ -344,8 +342,8 @@ github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/goccy/go-json v0.10.1 h1:lEs5Ob+oOG/Ze199njvzHbhn6p9T+h64F5hRj69iTTo=
|
||||
github.com/goccy/go-json v0.10.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
@ -377,6 +375,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -407,8 +406,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -419,6 +418,8 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -453,6 +454,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
@ -570,6 +572,8 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@ -577,6 +581,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
@ -611,7 +616,6 @@ github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd918
|
||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
@ -652,6 +656,14 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
|
||||
github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@ -793,6 +805,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -814,6 +828,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1016,10 +1032,11 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
@ -1100,8 +1117,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
|
||||
google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
|
@ -9,9 +9,12 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/dcarrillo/whatismyip/router"
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/quic-go/quic-go/http3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
@ -35,9 +38,12 @@ func buildContainer() testcontainers.ContainerRequest {
|
||||
"-tls-key", "/tmp/server.key",
|
||||
"-trusted-header", "X-Real-IP",
|
||||
"-enable-secure-headers",
|
||||
"-enable-http3",
|
||||
},
|
||||
ExposedPorts: []string{"8000:8000", "8001:8001"},
|
||||
WaitingFor: wait.ForLog("Starting TLS server listening on :8001"),
|
||||
ExposedPorts: []string{"8000:8000", "8001:8001", "8001:8001/udp"},
|
||||
WaitingFor: wait.ForHTTP("/geo").
|
||||
WithTLS(true, &tls.Config{InsecureSkipVerify: true}).
|
||||
WithPort("8001"),
|
||||
Mounts: testcontainers.Mounts(
|
||||
testcontainers.BindMount(
|
||||
filepath.Join(dir, "/../test/GeoIP2-City-Test.mmdb"),
|
||||
@ -69,28 +75,86 @@ func TestContainerIntegration(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := container.Terminate(ctx)
|
||||
err = container.Terminate(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
for _, url := range []string{"http://localhost:8000", "https://localhost:8001"} {
|
||||
client := &http.Client{}
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
resp, _ := client.Do(req)
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
quic bool
|
||||
}{
|
||||
{
|
||||
name: "RequestOverHTTP",
|
||||
url: "http://localhost:8000",
|
||||
quic: false,
|
||||
},
|
||||
{
|
||||
name: "RequestOverHTTPs",
|
||||
url: "https://localhost:8001",
|
||||
quic: false,
|
||||
},
|
||||
{
|
||||
name: "RequestOverUDPWithQuic",
|
||||
url: "https://localhost:8001",
|
||||
quic: true,
|
||||
},
|
||||
}
|
||||
|
||||
assert.NoError(t, json.Unmarshal(body, &router.JSONResponse{}))
|
||||
assert.Equal(t, "DENY", resp.Header.Get("X-Frame-Options"))
|
||||
assert.Equal(t, "nosniff", resp.Header.Get("X-Content-Type-Options"))
|
||||
assert.Equal(t, "1; mode=block", resp.Header.Get("X-Xss-Protection"))
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", tt.url, nil)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
var resp *http.Response
|
||||
var body []byte
|
||||
if tt.quic {
|
||||
resp, body, err = doQuicRequest(req)
|
||||
} else {
|
||||
client := &http.Client{}
|
||||
resp, _ = client.Do(req)
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
if strings.Contains(tt.url, "https://") {
|
||||
assert.Equal(t, `h3=":8001"; ma=2592000,h3-29=":8001"; ma=2592000`, resp.Header.Get("Alt-Svc"))
|
||||
}
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
assert.NoError(t, json.Unmarshal(body, &router.JSONResponse{}))
|
||||
assert.Equal(t, "DENY", resp.Header.Get("X-Frame-Options"))
|
||||
assert.Equal(t, "nosniff", resp.Header.Get("X-Content-Type-Options"))
|
||||
assert.Equal(t, "1; mode=block", resp.Header.Get("X-Xss-Protection"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func doQuicRequest(req *http.Request) (*http.Response, []byte, error) {
|
||||
roundTripper := &http3.RoundTripper{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
QuicConfig: &quic.Config{},
|
||||
}
|
||||
defer roundTripper.Close()
|
||||
|
||||
client := &http.Client{
|
||||
Transport: roundTripper,
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
|
||||
return resp, body, nil
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ type settings struct {
|
||||
TrustedHeader string
|
||||
TrustedPortHeader string
|
||||
EnableSecureHeaders bool
|
||||
EnableHTTP3 bool
|
||||
Server serverSettings
|
||||
version bool
|
||||
}
|
||||
@ -89,6 +90,12 @@ func Setup(args []string) (output string, err error) {
|
||||
false,
|
||||
"Add sane security-related headers to every response",
|
||||
)
|
||||
flags.BoolVar(
|
||||
&App.EnableHTTP3,
|
||||
"enable-http3",
|
||||
false,
|
||||
"Enable HTTP/3 protocol. HTTP/3 requires --tls-bind set, as HTTP/3 starts as a TLS connection that then gets upgraded to UDP. The UDP port is the same as the one used for the TLS server.",
|
||||
)
|
||||
|
||||
err = flags.Parse(args)
|
||||
if err != nil {
|
||||
@ -111,6 +118,10 @@ func Setup(args []string) (output string, err error) {
|
||||
return "", fmt.Errorf("in order to use TLS, the -tls-crt and -tls-key flags are mandatory")
|
||||
}
|
||||
|
||||
if App.EnableHTTP3 && App.TLSAddress == "" {
|
||||
return "", fmt.Errorf("in order to use HTTP3, the -tls-bind is mandatory")
|
||||
}
|
||||
|
||||
if App.TemplatePath != "" {
|
||||
info, err := os.Stat(App.TemplatePath)
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -41,6 +41,11 @@ func TestParseMandatoryFlags(t *testing.T) {
|
||||
"-tls-key", "/key-path",
|
||||
},
|
||||
},
|
||||
{
|
||||
[]string{
|
||||
"-geoip2-city", "/city-path", "-geoip2-asn", "/asn-path", "-enable-http3",
|
||||
},
|
||||
},
|
||||
{
|
||||
[]string{
|
||||
"-geoip2-city", "/city-path", "-geoip2-asn", "/asn-path", "-bind", ":8000",
|
||||
|
Loading…
Reference in New Issue
Block a user