Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 [Bug]: setting a Logger that access TLSConnectionState() will break when app.Server().MaxConnsPerIP is set to a value #2990

Open
3 tasks done
rabarar opened this issue Apr 27, 2024 · 7 comments

Comments

@rabarar
Copy link

rabarar commented Apr 27, 2024

Bug Description

There is a condition where the TLSConnectionState from Context( ) is nil - only when app.Server( ).MaxConnPerIP is set to a value.

How to Reproduce

  1. Create a new app
  2. Set the app.Server( ).MaxConnPerIP = 1
  3. use a custom logger
        DisableColors: false,
        Format:        "${date} ${time} ${ip} ${status} - ${method} ${path} ${yellow}SerialNo[${serialNumber}]\n",
        TimeFormat:    "2006-01-02 15:04:05",
        TimeZone:      "Local",
        CustomTags: map[string]logger.LogFunc{
            "serialNumber": func(output logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error) {
                return output.WriteString(outputSerialFromContext(c))

            },
        },
    }))
  1. receive an incoming route ...
  2. boom

Expected Behavior

no sigsegv

Fiber Version

v2@v2.52.4

Code Snippet (optional)

package main

import "github.com/gofiber/fiber/v3"
import "log"

func main() {
  app := fiber.New()

  // Steps to reproduce

  log.Fatal(app.Listen(":3000"))
}

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my problem prior to opening this one.
  • I understand that improperly formatted bug reports may be closed without explanation.
@ReneWerner87
Copy link
Member

ReneWerner87 commented Apr 27, 2024

Pls share the code for outputSerialFromContext

And the error message

@rabarar
Copy link
Author

rabarar commented Apr 28, 2024 via email

@ReneWerner87
Copy link
Member

You need to make a copy https://docs.gofiber.io/#zero-allocation

@rabarar
Copy link
Author

rabarar commented Apr 28, 2024 via email

@rabarar
Copy link
Author

rabarar commented Apr 28, 2024 via email

@rabarar
Copy link
Author

rabarar commented Apr 28, 2024

here's a small example that demonstrates the bug:

package main

import (
        "crypto"
        "crypto/tls"
        "fmt"
        "os"

        "github.com/gofiber/fiber/v2"
        //"golang.org/x/crypto/pkcs12"

        "github.com/gofiber/fiber/v2/log"
        "github.com/gofiber/fiber/v2/middleware/logger"
        "software.sslmate.com/src/go-pkcs12"
)

func initFiberApp() *fiber.App {
        app := fiber.New()
        app.Server().MaxConnsPerIP = 1

        app.Use(logger.New(logger.Config{
                DisableColors: false,
                Format:        "${date} ${time} ${ip} ${status} - ${method} ${path} ${yellow}SerialNo[${serialNumber}]\n",
                TimeFormat:    "2006-01-02 15:04:05",
                TimeZone:      "Local",
                CustomTags: map[string]logger.LogFunc{
                        "serialNumber": func(output logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error) {
                                return output.WriteString(c.Context().TLSConnectionState().PeerCertificates[0].SerialNumber.String())

                        },
                },
        }))

        app.Get("/", func(c *fiber.Ctx) error {
                if c.Context().TLSConnectionState() != nil && len(c.Context().TLSConnectionState().PeerCertificates) == 0 {
                        log.Warn("no peer certs")
                } else {
                        log.Info("peer certs exist")
                }
                return c.SendString(fmt.Sprintf("This page is being served over TLS using a PKCS12 store type: %s",
                        c.Context().TLSConnectionState().PeerCertificates[0].SerialNumber.String()))
        })

        return app
}

func initTLSConfig(path string, password string) (*tls.Certificate, error) {
        pkcs12Data, err := os.ReadFile(path)
        if err != nil {
                return nil, err
        }

        key, cert, _, err := pkcs12.DecodeChain(pkcs12Data, password)

        if err != nil {
                return nil, err
        }

        tlsCert := tls.Certificate{
                Certificate: [][]byte{cert.Raw},
                PrivateKey:  key.(crypto.PrivateKey),
                Leaf:        cert,
        }

        return &tlsCert, nil
}

func main() {
        path := "./security/server.p12"
        password := "foobar"

        tlsCert, error := initTLSConfig(path, password)

        if error != nil {
                fmt.Printf("Unable to initialize TLS configuration object. Check your configuration and try again. Program will STOP: %s", error)
        } else {
                config := &tls.Config{
                        Certificates: []tls.Certificate{*tlsCert},
                        ClientAuth:   tls.RequireAndVerifyClientCert,
                }

                app := initFiberApp()
                ln, err := tls.Listen("tcp", ":5443", config)
                if err != nil {
                        panic(err)
                }

                log.Fatal(app.Listener(ln))
        }
}

if you set MaxConnsPerIP > 0 you'll get a sigseg violation - the issue is in the worker pool implementation for fasthttps...

I think you can close this out and I should open it with their package...

@rabarar
Copy link
Author

rabarar commented Apr 29, 2024

FYI - from valyala/fasthttp "I have pushed a fix. I'll tag a release next week probably."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants