Skip to content

Commit

Permalink
Release/0.8.2 (#115)
Browse files Browse the repository at this point in the history
* Bump up APIFW version to 0.8.2

* Fix DNS resolver issue
  • Loading branch information
afr1ka authored Sep 24, 2024
1 parent 6593f3e commit 646ffb7
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 161 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION := 0.8.1
VERSION := 0.8.2

.DEFAULT_GOAL := build

Expand Down
39 changes: 32 additions & 7 deletions cmd/api-firewall/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"expvar" // Register the expvar handlers
"fmt"
"mime"
Expand Down Expand Up @@ -777,16 +778,40 @@ func runProxyMode(logger *logrus.Logger) error {
initialCap = 1
}

var dnsCacheResolver proxy.DNSCache
// default DNS resolver
resolver := &net.Resolver{
PreferGo: true,
StrictErrors: false,
}

// init DNS resolver
if cfg.DNS.Cache {
dnsCacheResolver, err = proxy.NewDNSResolver(cfg.DNS.FetchTimeout, cfg.DNS.LookupTimeout, &net.Resolver{PreferGo: true}, logger)
if err != nil {
return errors.Wrap(err, "DNS cache resolver init")
// configuration of the custom DNS server
if cfg.DNS.Nameserver.Host != "" {
var builder strings.Builder
builder.WriteString(cfg.DNS.Nameserver.Host)
builder.WriteString(":")
builder.WriteString(cfg.DNS.Nameserver.Port)

resolver.Dial = func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: cfg.DNS.LookupTimeout,
}
return d.DialContext(ctx, cfg.DNS.Nameserver.Proto, builder.String())
}
}

// init DNS resolver
dnsCacheOptions := proxy.DNSCacheOptions{
UseCache: cfg.DNS.Cache,
Logger: logger,
FetchTimeout: cfg.DNS.FetchTimeout,
LookupTimeout: cfg.DNS.LookupTimeout,
}

dnsResolver, err := proxy.NewDNSResolver(resolver, &dnsCacheOptions)
if err != nil {
return errors.Wrap(err, "DNS cache resolver init")
}

options := proxy.Options{
InitialPoolCapacity: initialCap,
ClientPoolCapacity: cfg.Server.ClientPoolCapacity,
Expand All @@ -798,7 +823,7 @@ func runProxyMode(logger *logrus.Logger) error {
DialTimeout: cfg.Server.DialTimeout,
DNSConfig: cfg.DNS,
}
pool, err := proxy.NewChanPool(host, &options, dnsCacheResolver)
pool, err := proxy.NewChanPool(host, &options, dnsResolver)
if err != nil {
return errors.Wrap(err, "proxy pool init")
}
Expand Down
16 changes: 12 additions & 4 deletions cmd/api-firewall/tests/main_dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/foxcpp/go-mockdns"
"github.com/sirupsen/logrus"

"github.com/wallarm/api-firewall/internal/config"
"github.com/wallarm/api-firewall/internal/platform/proxy"
)
Expand Down Expand Up @@ -49,13 +50,20 @@ func TestWithoutRCCDNSCacheBasic(t *testing.T) {
r := &net.Resolver{}
srv.PatchNet(r)

dnsCache, err := proxy.NewDNSResolver(cfg.DNS.FetchTimeout, cfg.DNS.LookupTimeout, r, logger)
dnsResolverOptions := proxy.DNSCacheOptions{
UseCache: true,
Logger: logger,
FetchTimeout: cfg.DNS.FetchTimeout,
LookupTimeout: cfg.DNS.LookupTimeout,
}

dnsCache, err := proxy.NewDNSResolver(r, &dnsResolverOptions)
if err != nil {
t.Fatal(err)
}
defer dnsCache.Stop()

addr, err := dnsCache.Fetch(context.Background(), "example.org")
addr, err := dnsCache.LookupIPAddr(context.Background(), "example.org")
if err != nil {
t.Error(err)
}
Expand All @@ -69,7 +77,7 @@ func TestWithoutRCCDNSCacheBasic(t *testing.T) {

time.Sleep(600 * time.Millisecond)

addr, err = dnsCache.Fetch(context.Background(), "example.org")
addr, err = dnsCache.LookupIPAddr(context.Background(), "example.org")
if err != nil {
t.Error(err)
}
Expand All @@ -81,7 +89,7 @@ func TestWithoutRCCDNSCacheBasic(t *testing.T) {

time.Sleep(800 * time.Millisecond)

addr, err = dnsCache.Fetch(context.Background(), "example.org")
addr, err = dnsCache.LookupIPAddr(context.Background(), "example.org")
if err != nil {
t.Error(err)
}
Expand Down
14 changes: 10 additions & 4 deletions cmd/api-firewall/tests/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2836,8 +2836,13 @@ func (s *ServiceTests) testCustomHostHeader(t *testing.T) {
Server: serverConf,
}

ipAddrs := []net.IPAddr{}
ipAddrs = append(ipAddrs, net.IPAddr{IP: net.IPv4(127, 0, 0, 1), Zone: ""})

s.dnsCache.EXPECT().LookupIPAddr(gomock.Any(), gomock.Any()).Return(ipAddrs, nil).Times(3)

options := proxy.Options{
InitialPoolCapacity: 100,
InitialPoolCapacity: 1,
ClientPoolCapacity: cfg.Server.ClientPoolCapacity,
InsecureConnection: cfg.Server.InsecureConnection,
RootCA: cfg.Server.RootCA,
Expand All @@ -2846,7 +2851,7 @@ func (s *ServiceTests) testCustomHostHeader(t *testing.T) {
WriteTimeout: cfg.Server.WriteTimeout,
DialTimeout: cfg.Server.DialTimeout,
}
pool, err := proxy.NewChanPool("localhost:28290", &options, nil)
pool, err := proxy.NewChanPool("localhost:28290", &options, s.dnsCache)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -2944,9 +2949,10 @@ func (s *ServiceTests) testDNSCacheFetch(t *testing.T) {
}

localIP := net.ParseIP("127.0.0.1")
ips := []net.IP{localIP}
ipAddrs := []net.IPAddr{}
ipAddrs = append(ipAddrs, net.IPAddr{IP: localIP, Zone: ""})

s.dnsCache.EXPECT().Fetch(gomock.Any(), gomock.Any()).Return(ips, nil).Times(3)
s.dnsCache.EXPECT().LookupIPAddr(gomock.Any(), gomock.Any()).Return(ipAddrs, nil).Times(3)

pool, err := proxy.NewChanPool("localhost:28290", &options, s.dnsCache)
if err != nil {
Expand Down
Binary file modified cmd/api-firewall/tests/wallarm_api2_update.db
Binary file not shown.
2 changes: 1 addition & 1 deletion demo/docker-compose/OWASP_CoreRuleSet/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3.8"
services:
api-firewall:
container_name: api-firewall
image: wallarm/api-firewall:v0.8.1
image: wallarm/api-firewall:v0.8.2
restart: on-failure
environment:
APIFW_URL: "http://0.0.0.0:8080"
Expand Down
2 changes: 1 addition & 1 deletion demo/docker-compose/docker-compose-api-mode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: '3.8'
services:
api-firewall:
container_name: api-firewall
image: wallarm/api-firewall:v0.8.1
image: wallarm/api-firewall:v0.8.2
restart: on-failure
environment:
APIFW_MODE: "api"
Expand Down
2 changes: 1 addition & 1 deletion demo/docker-compose/docker-compose-graphql-mode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: '3.8'
services:
api-firewall:
container_name: api-firewall
image: wallarm/api-firewall:v0.8.1
image: wallarm/api-firewall:v0.8.2
restart: on-failure
environment:
APIFW_MODE: "graphql"
Expand Down
2 changes: 1 addition & 1 deletion demo/docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3.8"
services:
api-firewall:
container_name: api-firewall
image: wallarm/api-firewall:v0.8.1
image: wallarm/api-firewall:v0.8.2
restart: on-failure
environment:
APIFW_URL: "http://0.0.0.0:8080"
Expand Down
4 changes: 4 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

This page describes new releases of Wallarm API Firewall.

## v0.8.2 (2024-09-24)

* Fixed DNS resolver cache issue

## v0.8.1 (2024-09-13)

* Fixed incorrect request to get API specification structure issue
Expand Down
2 changes: 1 addition & 1 deletion helm/api-firewall/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v1
name: api-firewall
version: 0.7.1
appVersion: 0.8.1
appVersion: 0.8.2
description: Wallarm OpenAPI-based API Firewall
home: https://github.com/wallarm/api-firewall
icon: https://static.wallarm.com/wallarm-logo.svg
Expand Down
96 changes: 35 additions & 61 deletions internal/platform/proxy/chainpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,32 @@ import (
"github.com/wallarm/api-firewall/internal/config"
)

const defaultConcurrency = 1000

var (
errInvalidCapacitySetting = errors.New("invalid capacity settings")
errClosed = errors.New("err: chan closed")
errClosed = errors.New("chan closed")
errInvalidDNSResolver = errors.New("invalid DNS resolver")
)

func (p *chanPool) tryResolveAndFetchOneIP(host string) (string, error) {

var ips []net.IP
var resolvedIP string
var err error

if p.dnsCacheResolver != nil {
ips, err = p.dnsCacheResolver.Fetch(context.Background(), host)
if err != nil {
return "", err
}
} else {
// resolve host using local resolver
ips, err = p.defaultResolver.LookupIP(context.Background(), "ip", host)
if err != nil {
return "", err
}
ipAddrs, err := p.dnsResolver.LookupIPAddr(context.Background(), host)
if err != nil {
return "", err
}

for _, ip := range ips {
if ip.To4() != nil {
for _, ip := range ipAddrs {
if ip.IP.To4() != nil {
resolvedIP = ip.String()
return resolvedIP, nil
}
}

for _, ip := range ips {
if ip.To16() != nil {
for _, ip := range ipAddrs {
if ip.IP.To16() != nil {
resolvedIP = ip.String()
return resolvedIP, nil
}
Expand All @@ -73,21 +66,19 @@ func (p *chanPool) factory(connAddr string) HTTPClient {
DisableHeaderNamesNormalizing: true,
DisablePathNormalizing: true,
Dial: func(addr string) (net.Conn, error) {
return fasthttp.DialTimeout(connAddr, p.options.DialTimeout)
tcpDialer := &fasthttp.TCPDialer{
Concurrency: defaultConcurrency,
Resolver: p.dnsResolver,
DisableDNSResolution: p.options.DNSConfig.Cache,
}
return tcpDialer.DialTimeout(connAddr, p.options.DialTimeout)
},
TLSConfig: p.tlsConfig,
MaxConnsPerHost: p.options.MaxConnsPerHost,
ReadTimeout: p.options.ReadTimeout,
WriteTimeout: p.options.WriteTimeout,
}

// use configured NS
if p.options.DNSConfig.Nameserver.Host != "" {
proxyClient.Dial = (&fasthttp.TCPDialer{
Resolver: p.defaultResolver,
}).Dial
}

return &proxyClient
}

Expand Down Expand Up @@ -121,9 +112,8 @@ type chanPool struct {
initResolvedIP string
initConnAddr string

tlsConfig *tls.Config
defaultResolver *net.Resolver
dnsCacheResolver DNSCache
tlsConfig *tls.Config
dnsResolver DNSCache
}

type Options struct {
Expand All @@ -140,11 +130,15 @@ type Options struct {
}

// NewChanPool to new a pool with some params
func NewChanPool(hostAddr string, options *Options, dnsCacheResolver DNSCache) (Pool, error) {
func NewChanPool(hostAddr string, options *Options, dnsResolver DNSCache) (Pool, error) {
if options.InitialPoolCapacity < 0 || options.ClientPoolCapacity <= 0 || options.InitialPoolCapacity > options.ClientPoolCapacity {
return nil, errInvalidCapacitySetting
}

if dnsResolver == nil {
return nil, errInvalidDNSResolver
}

// Get the SystemCertPool, continue with an empty pool on error
rootCAs, err := x509.SystemCertPool()
if err != nil {
Expand Down Expand Up @@ -182,23 +176,7 @@ func NewChanPool(hostAddr string, options *Options, dnsCacheResolver DNSCache) (
host: host,
port: port,
tlsConfig: tlsConfig,
defaultResolver: &net.Resolver{
PreferGo: true,
},
dnsCacheResolver: dnsCacheResolver,
}

// init NS in the DNS resolver
if options.DNSConfig.Nameserver.Host != "" {
var builder strings.Builder
builder.WriteString(options.DNSConfig.Nameserver.Host)
builder.WriteString(":")
builder.WriteString(options.DNSConfig.Nameserver.Port)

pool.defaultResolver.Dial = func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{}
return d.DialContext(ctx, options.DNSConfig.Nameserver.Proto, builder.String())
}
dnsResolver: dnsResolver,
}

ip, err := pool.tryResolveAndFetchOneIP(host)
Expand All @@ -220,20 +198,18 @@ func NewChanPool(hostAddr string, options *Options, dnsCacheResolver DNSCache) (

connAddr := pool.initConnAddr

if pool.dnsCacheResolver != nil {
ip, err = pool.tryResolveAndFetchOneIP(pool.host)
if err != nil {
continue
}
ip, err = pool.tryResolveAndFetchOneIP(pool.host)
if err != nil {
continue
}

builder.Reset()
builder.Reset()

builder.WriteString(ip)
builder.WriteString(":")
builder.WriteString(port)
builder.WriteString(ip)
builder.WriteString(":")
builder.WriteString(port)

connAddr = builder.String()
}
connAddr = builder.String()

proxy := pool.factory(connAddr)
if pool.reverseProxyChanLB[ip] == nil {
Expand Down Expand Up @@ -261,9 +237,7 @@ func (p *chanPool) Close() {
close(reverseProxyChan)
}

if p.dnsCacheResolver != nil {
p.dnsCacheResolver.Stop()
}
p.dnsResolver.Stop()

}

Expand Down
Loading

0 comments on commit 646ffb7

Please sign in to comment.