diff --git a/imports.go b/imports.go index 24d33f9..eba78d3 100644 --- a/imports.go +++ b/imports.go @@ -24,4 +24,5 @@ import ( _ "github.com/mholt/caddy-l4/modules/l4tee" _ "github.com/mholt/caddy-l4/modules/l4throttle" _ "github.com/mholt/caddy-l4/modules/l4tls" + _ "github.com/mholt/caddy-l4/modules/l4xmpp" ) diff --git a/modules/l4tls/alpn_matcher.go b/modules/l4tls/alpn_matcher.go new file mode 100644 index 0000000..24bb537 --- /dev/null +++ b/modules/l4tls/alpn_matcher.go @@ -0,0 +1,53 @@ +// Copyright 2020 Matthew Holt +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package l4tls + +import ( + "crypto/tls" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/modules/caddytls" +) + +func init() { + caddy.RegisterModule(MatchALPN{}) +} + +type MatchALPN []string + +// CaddyModule returns the Caddy module information. +func (MatchALPN) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "tls.handshake_match.alpn", + New: func() caddy.Module { return new(MatchALPN) }, + } +} + +func (m MatchALPN) Match(hello *tls.ClientHelloInfo) bool { + clientProtocols := hello.SupportedProtos + for _, alpn := range m { + for _, clientProtocol := range clientProtocols { + if alpn == string(clientProtocol) { + return true + } + } + } + return false +} + +// Interface guards +var ( + _ caddytls.ConnectionMatcher = (*MatchALPN)(nil) +) diff --git a/modules/l4xmpp/matcher.go b/modules/l4xmpp/matcher.go new file mode 100644 index 0000000..b9a2d45 --- /dev/null +++ b/modules/l4xmpp/matcher.go @@ -0,0 +1,54 @@ +// Copyright 2020 Matthew Holt +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package l4xmpp + +import ( + "io" + "strings" + + "github.com/caddyserver/caddy/v2" + "github.com/mholt/caddy-l4/layer4" +) + +func init() { + caddy.RegisterModule(MatchXMPP{}) +} + +// MatchXMPP is able to match XMPP connections. +type MatchXMPP struct{} + +// CaddyModule returns the Caddy module information. +func (MatchXMPP) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "layer4.matchers.xmpp", + New: func() caddy.Module { return new(MatchXMPP) }, + } +} + +// Match returns true if the connection looks like XMPP. +func (m MatchXMPP) Match(cx *layer4.Connection) (bool, error) { + p := make([]byte, minXmppLength) + n, err := io.ReadFull(cx, p) + if err != nil || n < minXmppLength { // needs at least 50 (fix for adium/pidgin) + return false, nil + } + return strings.Contains(string(p), xmppWord), nil +} + +var xmppWord = "jabber" +var minXmppLength = 50 + +// Interface guard +var _ layer4.ConnMatcher = (*MatchXMPP)(nil)