From 0c7bdb8cc5939cc9ecc929c7294b464030a7fab2 Mon Sep 17 00:00:00 2001 From: Neur0toxine Date: Fri, 8 Nov 2024 17:23:44 +0300 Subject: [PATCH] initial --- .gitignore | 27 ++++++++++++++++++++++++ Dockerfile | 25 ++++++++++++++++++++++ LICENSE.md | 21 +++++++++++++++++++ README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ compose.yaml | 14 +++++++++++++ go.mod | 3 +++ main.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 202 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 compose.yaml create mode 100644 go.mod create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dfaa352 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +### `.gitignore` +```gitignore +# Binaries +main + +# Vendor directory +/vendor/ + +# Go build artifacts +*.exe +*.dll +*.so +*.dylib + +# IDE and editor settings +.idea/ +.vscode/ +*.swp + +# Log files +*.log + +# Environment variables +.env + +# Docker-related +docker-compose.override.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..93250d1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Build stage +FROM golang:1.23-alpine AS builder +WORKDIR /app + +# Copy and download dependencies +# COPY go.mod go.sum ./ +COPY go.mod ./ +RUN go mod download + +# Copy the source code +COPY . . + +# Build the application +RUN go build -o main . + +# Runtime stage +FROM alpine:latest +WORKDIR /root/ +COPY --from=builder /app/main . + +# Expose the port the service will run on +EXPOSE 8080 + +# Command to run the executable +ENTRYPOINT ["./main"] diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..1521dda --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Neur0toxine + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b73007d --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# real-ip-request-printer + +## Overview +`real-ip-request-printer` is a simple Go service that listens for HTTP `GET` requests on the root endpoint (`/`) and responds with: +- The request IP address as seen by the application (considering headers like `X-Real-Ip` and `X-Forwarded-For`). +- All incoming HTTP headers in a `key: value` format. + +This project is designed to help inspect and debug HTTP request information, particularly for applications deployed behind proxies or load balancers. + +## How to Run + +### Prerequisites +- [Go](https://golang.org/dl/) (for local builds) +- [Docker](https://www.docker.com/get-started) and [Docker Compose](https://docs.docker.com/compose/) + +### Running Locally +1. Clone the repository: +```sh +git clone https://github.com/yourusername/real-ip-request-printer.git +cd real-ip-request-printer +``` +2. Build and run the Go application: + +```sh +go mod tidy +go run main.go +``` + +The service will start on http://localhost:8080 by default. You can change the listening address by setting the LISTEN environment variable: + +```sh +LISTEN=127.0.0.1:9090 go run main.go +``` + +### Running with Docker +Change the hostname in the `compose.yaml` to your domain. Build and run the Docker container using Compose: + +```sh +docker compose up +``` + +Access the service via the configured domain. + +### Configuration +- The listening address of the Go service can be customized using the LISTEN environment variable. +- For containerized execution use Traefik for routing. + +### Project Structure +- `main.go`: The main Go application. +- `Dockerfile`: Configuration for building the Docker image. +- `compose.yaml`: Docker Compose configuration to run the service. +- `README.md`: This documentation file. +- `LICENSE.md`: License file. +- `.gitignore`: Standard git ignore settings for Go projects. + +### License + +This project is open-source and available under the [MIT License](LICENSE.md). \ No newline at end of file diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..0305aba --- /dev/null +++ b/compose.yaml @@ -0,0 +1,14 @@ +services: + realipprinter: + build: + context: . + dockerfile: Dockerfile + ports: + - 3001:8080 + environment: + - LISTEN=0.0.0.0:8080 + labels: + - "traefik.enable=true" + - "traefik.http.routers.realipprinter.rule=Host(`realipoutput.proxy.neur0tx.site`)" + - "traefik.http.routers.realipprinter.entrypoints=web" + - "traefik.http.services.realipprinter.loadbalancer.server.port=8080" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..38c75aa --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module real-ip-request-printer + +go 1.22.0 diff --git a/main.go b/main.go new file mode 100644 index 0000000..5518853 --- /dev/null +++ b/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "net/http" + "os" + "strings" +) + +func getClientIP(r *http.Request) string { + // Check common headers for real client IP + if ip := r.Header.Get("X-Real-Ip"); ip != "" { + return ip + } + if forwardedFor := r.Header.Get("X-Forwarded-For"); forwardedFor != "" { + ips := strings.Split(forwardedFor, ",") + return strings.TrimSpace(ips[0]) + } + // Fallback to remote address + return r.RemoteAddr +} + +func handler(w http.ResponseWriter, r *http.Request) { + // Set content type + w.Header().Set("Content-Type", "text/plain") + + // Get client IP + clientIP := getClientIP(r) + + // Write response + fmt.Fprintf(w, "Request IP: %s\n", clientIP) + fmt.Fprintln(w, "Headers:") + + for name, values := range r.Header { + for _, value := range values { + fmt.Fprintf(w, "%s: %s\n", name, value) + } + } +} + +func main() { + // Get the listen address from the environment variable or use default + listenAddr := os.Getenv("LISTEN") + if listenAddr == "" { + listenAddr = "0.0.0.0:8080" + } + + http.HandleFunc("/", handler) + + fmt.Printf("Starting server on %s\n", listenAddr) + if err := http.ListenAndServe(listenAddr, nil); err != nil { + fmt.Printf("Error starting server: %s\n", err) + } +}