Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 60 additions & 7 deletions caddyconfig/httpcaddyfile/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"go.uber.org/zap"
)

// mapAddressToProtocolToServerBlocks returns a map of listener address to list of server
Expand Down Expand Up @@ -307,29 +308,75 @@ func (st *ServerType) listenersForServerBlockAddress(sblock serverBlock, addr Ad
}

// the bind directive specifies hosts (and potentially network), and the protocols to serve them with, but is optional
lnCfgVals := make([]addressesWithProtocols, 0, len(sblock.pile["bind"]))
lnCfgVals := make([]bindOptions, 0, len(sblock.pile["bind"]))
for _, cfgVal := range sblock.pile["bind"] {
if val, ok := cfgVal.Value.(addressesWithProtocols); ok {
if val, ok := cfgVal.Value.(bindOptions); ok {
lnCfgVals = append(lnCfgVals, val)
}
}
if len(lnCfgVals) == 0 {
if defaultBindValues, ok := options["default_bind"].([]ConfigValue); ok {
for _, defaultBindValue := range defaultBindValues {
lnCfgVals = append(lnCfgVals, defaultBindValue.Value.(addressesWithProtocols))
lnCfgVals = append(lnCfgVals, defaultBindValue.Value.(bindOptions))
}
} else {
lnCfgVals = []addressesWithProtocols{{
addresses: []string{""},
protocols: nil,
lnCfgVals = []bindOptions{{
addresses: []string{""},
interfaces: nil,
protocols: nil,
}}
}
}

// use a map to prevent duplication
interfaceAddresses := map[string][]string{}
listeners := map[string]map[string]struct{}{}
for _, lnCfgVal := range lnCfgVals {
for _, lnAddr := range lnCfgVal.addresses {
addresses := []string{}
addresses = append(addresses, lnCfgVal.addresses...)
for _, lnIface := range lnCfgVal.interfaces {
lnNetw, lnDevice, _, err := caddy.SplitNetworkAddress(lnIface)
if err != nil {
return nil, fmt.Errorf("splitting listener interface: %v", err)
}

ifaceAddresses, ok := interfaceAddresses[lnDevice]
if !ok {
iface, err := net.InterfaceByName(lnDevice)
if err != nil {
return nil, fmt.Errorf("querying listener interface: %v: %v", lnDevice, err)
}
if iface == nil {
return nil, fmt.Errorf("querying listener interface: %v", lnDevice)
}
ifaceAddrs, err := iface.Addrs()
if err != nil {
return nil, fmt.Errorf("querying listener interface addresses: %v: %v", lnDevice, err)
}
for _, ifaceAddr := range ifaceAddrs {
var ip net.IP
switch ifaceAddrValue := ifaceAddr.(type) {
case *net.IPAddr:
ip = ifaceAddrValue.IP
case *net.IPNet:
ip = ifaceAddrValue.IP
default:
caddy.Log().Error("reading listener interface address", zap.String("device", lnDevice), zap.String("address", ifaceAddr.String()))
continue
}

if len(ip) == net.IPv4len && caddy.IsIPv4Network(lnNetw) || len(ip) == net.IPv6len && caddy.IsIPv6Network(lnNetw) {
ifaceAddresses = append(ifaceAddresses, caddy.JoinNetworkAddress(lnNetw, ip.String(), ""))
}
}
if len(ifaceAddresses) == 0 {
return nil, fmt.Errorf("querying listener interface addresses for network: %v: %v", lnDevice, lnNetw)
}
interfaceAddresses[lnDevice] = ifaceAddresses
}
addresses = append(addresses, ifaceAddresses...)
}
for _, lnAddr := range addresses {
lnNetw, lnHost, _, err := caddy.SplitNetworkAddress(lnAddr)
if err != nil {
return nil, fmt.Errorf("splitting listener address: %v", err)
Expand All @@ -350,6 +397,12 @@ func (st *ServerType) listenersForServerBlockAddress(sblock serverBlock, addr Ad
return listeners, nil
}

type bindOptions struct {
addresses []string
interfaces []string
protocols []string
}

// addressesWithProtocols associates a list of listen addresses
// with a list of protocols to serve them with
type addressesWithProtocols struct {
Expand Down
21 changes: 14 additions & 7 deletions caddyconfig/httpcaddyfile/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,22 @@ func init() {

// parseBind parses the bind directive. Syntax:
//
// bind <addresses...> [{
// protocols [h1|h2|h2c|h3] [...]
// }]
// bind <addresses...> [{
// interfaces <devices...>
// protocols [h1|h2|h2c|h3] [...]
// }]
func parseBind(h Helper) ([]ConfigValue, error) {
h.Next() // consume directive name
var addresses, protocols []string
var addresses, interfaces, protocols []string
addresses = h.RemainingArgs()

for h.NextBlock(0) {
switch h.Val() {
case "interfaces":
interfaces = h.RemainingArgs()
if len(interfaces) == 0 {
return nil, h.Errf("interfaces requires one or more arguments")
}
case "protocols":
protocols = h.RemainingArgs()
if len(protocols) == 0 {
Expand All @@ -77,9 +83,10 @@ func parseBind(h Helper) ([]ConfigValue, error) {
}
}

return []ConfigValue{{Class: "bind", Value: addressesWithProtocols{
addresses: addresses,
protocols: protocols,
return []ConfigValue{{Class: "bind", Value: bindOptions{
addresses: addresses,
interfaces: interfaces,
protocols: protocols,
}}}, nil
}

Expand Down