github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/modules/l4ssh/matcher.go (about) 1 // Copyright 2020 Matthew Holt 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package l4ssh 16 17 import ( 18 "bytes" 19 "io" 20 21 "github.com/caddyserver/caddy/v2" 22 "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 23 24 "github.com/mholt/caddy-l4/layer4" 25 ) 26 27 func init() { 28 caddy.RegisterModule(&MatchSSH{}) 29 } 30 31 // MatchSSH is able to match SSH connections. 32 type MatchSSH struct{} 33 34 // CaddyModule returns the Caddy module information. 35 func (*MatchSSH) CaddyModule() caddy.ModuleInfo { 36 return caddy.ModuleInfo{ 37 ID: "layer4.matchers.ssh", 38 New: func() caddy.Module { return new(MatchSSH) }, 39 } 40 } 41 42 // Match returns true if the connection looks like SSH. 43 func (m *MatchSSH) Match(cx *layer4.Connection) (bool, error) { 44 p := make([]byte, len(sshPrefix)) 45 _, err := io.ReadFull(cx, p) 46 if err != nil { 47 return false, err 48 } 49 return bytes.Equal(p, sshPrefix), nil 50 } 51 52 var sshPrefix = []byte("SSH-") 53 54 // UnmarshalCaddyfile sets up the MatchSSH from Caddyfile tokens. Syntax: 55 // 56 // ssh 57 func (m *MatchSSH) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 58 _, wrapper := d.Next(), d.Val() // consume wrapper name 59 60 // No same-line options are supported 61 if d.CountRemainingArgs() > 0 { 62 return d.ArgErr() 63 } 64 65 // No blocks are supported 66 if d.NextBlock(d.Nesting()) { 67 return d.Errf("malformed layer4 connection matcher '%s': blocks are not supported", wrapper) 68 } 69 70 return nil 71 } 72 73 // Interface guards 74 var ( 75 _ layer4.ConnMatcher = (*MatchSSH)(nil) 76 _ caddyfile.Unmarshaler = (*MatchSSH)(nil) 77 )