diff --git a/src/conn.rs b/src/conn.rs
index 1c7ee3ae2aa2d3c50b1a1ce17a0196e4148b8e98..31fd5698434c58e03b22065196de60f2c156ac71 100644
--- a/src/conn.rs
+++ b/src/conn.rs
@@ -100,7 +100,7 @@ impl Conn {
         Ok(Conn {
             sess_id: None,
             kex: Kex::new(),
-            remote_version: ident::RemoteVersion::new(),
+            remote_version: ident::RemoteVersion::new(cliserv.is_client()),
             state: ConnState::SendIdent,
             algo_conf,
             cliserv,
diff --git a/src/ident.rs b/src/ident.rs
index 49f28d3cbd35c9a1de5bb6096d09c59ce994eb51..b38b214d690966ecfa7e72f8800661e42e102d8b 100644
--- a/src/ident.rs
+++ b/src/ident.rs
@@ -33,6 +33,7 @@ pub struct RemoteVersion {
     /// Parse state
     st: VersPars,
     num_lines: usize,
+    is_client: bool,
 }
 
 /// Version parsing state.
@@ -59,11 +60,12 @@ pub(crate) enum VersPars {
 }
 
 impl RemoteVersion {
-    pub fn new() -> Self {
+    pub fn new(is_client: bool) -> Self {
         RemoteVersion {
             storage: [0; MAX_REMOTE_VERSION_LEN],
             st: VersPars::Start(0),
             num_lines: 0,
+            is_client,
         }
     }
 
@@ -113,7 +115,8 @@ impl RemoteVersion {
                     if b == LF {
                         self.st = VersPars::Start(0);
                         self.num_lines += 1;
-                        if self.num_lines > MAX_LINES {
+                        // only client allows extra unknown lines
+                        if !self.is_client || self.num_lines > MAX_LINES {
                             return Err(Error::NotSSH);
                         }
                     }
@@ -160,8 +163,9 @@ mod tests {
     use crate::error::{Error,TrapBug,Result};
     use crate::sunsetlog::init_test_log;
 
+    // Tests as a client, allowing leading ignored lines
     fn test_version(v: &str, split: usize, expect: &str) -> Result<usize> {
-        let mut r = ident::RemoteVersion::new();
+        let mut r = ident::RemoteVersion::new(true);
 
         let split = split.min(v.len());
         let (a, b) = v.as_bytes().split_at(split);
@@ -212,6 +216,19 @@ mod tests {
         Ok(())
     }
 
+
+    #[test]
+    /// check server doesn't allow leading lines
+    fn version_server_lines() -> Result<()> {
+        // server instance, is_client false
+        let mut r = ident::RemoteVersion::new(false);
+        r.consume(b"SSH-2.0-aaa").unwrap();
+        let mut r = ident::RemoteVersion::new(false);
+        // disallow leading lines
+        r.consume(b"zzz\x0d\x0aSSH-2.0-aaa").unwrap_err();
+        Ok(())
+    }
+
     // // TODO: maybe fuzzing would work better.
     // // also hits an ICE, perhaps
     // // https://github.com/rust-lang/rust/pull/94391
diff --git a/src/kex.rs b/src/kex.rs
index f9e81f0fd7b455a9fa118c72aeec5c173e7e6a05..4d80fcae49344794e6c6d27559d611b8bde2aa5f 100644
--- a/src/kex.rs
+++ b/src/kex.rs
@@ -896,7 +896,7 @@ mod tests {
     impl TrafCatcher {
         fn new() -> Self {
             let traf_in = traffic::TrafIn::new(vec![0u8; 3000].leak());
-            let mut rv = RemoteVersion::new();
+            let mut rv = RemoteVersion::new(false);
             rv.consume(b"SSH-2.0-thing\r\n").unwrap();
             rv.version().unwrap();
 
@@ -958,7 +958,7 @@ mod tests {
         // needs to be hardcoded because that's what we send.
         let mut s = Vec::from(crate::ident::OUR_VERSION);
         s.extend_from_slice(b"\r\n");
-        let mut version = RemoteVersion::new();
+        let mut version = RemoteVersion::new(true);
         version.consume(s.as_slice()).unwrap();
 
         let mut keys = vec![];