标签 SSH 下的文章

我理解公钥私钥只是一个更加复杂的密码

倘若我本身密码就是 16 位以上大小写英文数字符号混合,并且每个服务器密码均随机生成不一样
并且我开启了 auto-ban 之类的服务,防止穷举猜测密码

那是否可以认为安全性是接近的
特别如果是私钥泄露意味你几乎所有服务器等于密码泄露,难道是每个服务器私钥都不一样?

  1. 物理机直接安装 ubuntu, 所有应用都部署在 docker
  2. ssh 只允许密钥登录, 禁止 root 用户登录
  3. 所有访问( http, tcp)都通过 nginx 代理, ufw 只暴露固定的几个端口, nginx 开启 https 证书
  4. nginx 配置 geolite2, 禁止任何 国外 ip 访问, 异常访问基本都是国外 ip
  5. fail2ban 自动封禁所有 nginx 日志里面国外 ip
  6. 不安装 1panel,宝塔等任何 web 管理工具, 直接 ssh 到机器上命令行管理

分享下我的 nginx 配置

load_module "modules/ngx_http_geoip2_module.so";
load_module "modules/ngx_stream_geoip2_module.so";

worker_processes 4;

error_log /var/log/nginx/nginx_error.log;
error_log /var/log/nginx/nginx_error.log notice;
error_log /var/log/nginx/nginx_error.log info;

pid /var/log/nginx/nginx.pid;

events {
    worker_connections 1024;
}


http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
      auto_reload 24h;
      $geoip_country_code  default=Unknown source=$remote_addr country iso_code;
      $geoip_country_name  country  names  en;
    }
    geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb {
      auto_reload 24h;
      $geoip_city   default=Unknown city names en;
    }

    map $geoip_country_code $allowed_country {
        default no;
        CN yes;
    }

    map $remote_addr $allowed {
        default $allowed_country;
        127.0.0.1 yes;
        ~^192\.168\.\\d+\.\\d+$ yes;
        ~^172\.16\.0\.\\d+$ yes;
        ~^172\.17\.\\d+\.\\d+$ yes;
    }

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' "";
    }

    log_format json_analytics escape=json '{'
    '"timestamp": "$msec", ' # request unixtime in seconds with a milliseconds resolution
    '"request_id": "$request_id", ' # the unique request id
    '"request_length": "$request_length", ' # request length (including headers and body)
    '"body_bytes_sent": "$body_bytes_sent", '
    '"remote_addr": "$remote_addr", ' # client IP
    '"time_iso8601": "$time_iso8601", '
    '"request_uri": "$request_uri", ' # full path and arguments if the request
    '"code": "$status", ' # response status code
    '"http_host": "$http_host", ' # the request Host: header
    '"server_name": "$server_name", ' # the name of the vhost serving the request
    '"request_time": "$request_time", ' # request processing time in seconds with msec resolution
    '"upstream": "$upstream_addr", ' # upstream backend server for proxied requests
    '"request_method": "$request_method", ' # request method
    '"allowed": "$allowed", '
    '"geoip_country_code": "$geoip_country_code", '
    '"geoip_country_name": "$geoip_country_name", '
    '"geoip_city": "$geoip_city"'
    '}';

    access_log /var/log/nginx/access.log json_analytics;
    error_log /var/log/nginx/error.log warn;

    set_real_ip_from 0.0.0.0/0;
    real_ip_header X-Real-IP;
    real_ip_recursive on;

    sendfile on;
    server_tokens off;
    keepalive_timeout 65;

    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    proxy_buffering off;
    proxy_buffers 4 128k;
    proxy_buffer_size 256k;
    proxy_busy_buffers_size 256k;



    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ALL:!DH:!EXPORT:!RC4:+HIGH:+MEDIUM:-LOW:!aNULL:!eNULL;

    ssl_certificate /etc/nginx/ssl/fullchain.cer;
    ssl_certificate_key /etc/nginx/ssl/xxx.cc.key;


    include /etc/nginx/conf.d/*.conf;

}


stream {

    geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
      auto_reload 24h;
      $geoip_country_code  default=Unknown source=$remote_addr country iso_code;
      $geoip_country_name  country  names  en;
    }
    geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb {
      auto_reload 24h;
      $geoip_city   default=Unknown city names en;
    }



    map $geoip_country_code $allowed_country {
        default no;
        CN yes;
    }

    map $remote_addr $allowed {
        default $allowed_country;
        127.0.0.1 yes;
        ~^192\.168\.\\d+\.\\d+$ yes;
        ~^172\.16\.0\.\\d+$ yes;
        ~^172\.17\.\\d+\.\\d+$ yes;
    }

    log_format json_analytics escape=json '{'
    '"timestamp": "$msec", ' # request unixtime in seconds with a milliseconds resolution
    '"connection": "$connection", ' # connection serial number
    '"pid": "$pid", ' # process pid
    '"remote_addr": "$remote_addr", ' # client IP
    '"remote_port": "$remote_port", ' # client port
    '"time_iso8601": "$time_iso8601", ' # local time in the ISO 8601 standard format
    '"upstream": "$upstream_addr", '
    '"protocol": "$protocol", '
    '"allowed": "$allowed", '
    '"request_method": "STREAM", '
    '"geoip_country_code": "$geoip_country_code", '
    '"geoip_country_name": "$geoip_country_name", '
    '"geoip_city": "$geoip_city"'
    '}';

    access_log /var/log/nginx/access.log json_analytics;
    error_log /var/log/nginx/error.log warn;

    include /etc/nginx/stream.d/*.conf;
}

ssh 代理

map $allowed $ssh_server {
    yes ssh;
}

upstream ssh {
    server  192.168.5.1:1234;
}

server {
    listen    5678;
    listen [::]:5678;
    proxy_pass $ssh_server;
    proxy_connect_timeout 30s;
    proxy_timeout 60s;

    ssl_preread on;
}

http 代理

server {
    server_name x.x.com;
    listen 1233 ssl;
    listen [::]:1233 ssl;

    http2 on;
    charset "utf-8";

    if ($allowed != yes) {
        return 404;
    }

    error_page 497 =307 https://$host:$server_port$request_uri;

    client_max_body_size 512M;
    proxy_buffering off;


    set $backend "http://192.168.5.1:1234";
    include /etc/nginx/conf.d/basic/no_log.conf;

    location / {
        proxy_redirect off;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass $backend;
    }

}

🚀 ZenSSH —— 简单、轻量、安全的 SSH 工具

大家好,给大家推荐一个我最近做的开源项目:ZenSSH,一款实用的 SSH 工具。
当前处于早期测试版,开发人员就我自己,也是针对我自己的需求才做的,市面上大部分 SSH 工具连个配置同步都收费,又或者没有全平台覆盖,不同平台装不一样的软件配置同步更别说了;又或者一堆堆的功能,实际我就是想简单的连接到服务器上,简单运维一下。
适合开发者、运维工程师,基于 Tauri 构建,提供全平台覆盖(不过我没有 iPhone 所以没有构建),配置同步通过 GitHub 或 Gitee 的 Gist 实现,支持 SSH 和 SFTP ,并且支持跳板机连接。

👉 项目链接:
https://github.com/kisChang/ZenSSH

✨ 项目亮点

🔐 专注 SSH — ZenSSH 致力于提供跨平台的 SSH 客户端,配置同步,随时随地登录服务器。

📦 开源免费 — 完全开源免费,代码托管在 GitHub 上,欢迎大家查看、使用和贡献代码。

🛠 轻量易用 — 与传统的繁琐配置相比,ZenSSH 更强调上手速度和用户体验,适合日常快速 SSH 连接、文件上下载等需求。

✨ 说明

稳定性 — 早期测试版本,我也只测试了基础功能(在 Android 、Linux 、Windows 上),已经在日常使用了,有问题随时反馈到 issues ,同样感谢贡献代码~

开源协议 — 现在只公开了前端代码,rust 代码也托管在了 GitHub 但暂时没有开源,后续会考虑开源,整体构建都是基于 GitHub Actions ,安全性可以放心。

点赞 + 关注 + 收藏 = 学会了

整理了一个NAS小专栏,有兴趣的工友可以关注一下 👉 《NAS邪修》

有些非技术出身的工友入手NAS后,只用来存照片、存电影,却不知道开启SSH后,NAS能变得更强大、更好用。其实SSH一点都不复杂,不用懂代码、不用搞技术,跟着这篇教程,就能轻松开启SSH,用电脑远程操控NAS。

先搞明白核心问题:我们为什么要费功夫开启SSH?

SSH简单说就是「安全的远程操控通道」。相当于给你的NAS装了一把“远程钥匙”,不用NAS客户端,不用浏览器也能让电脑操控NAS做一些事情。

有时候用 Docker 客户端拉不下的镜像,用 ssh 的方式可能能拉下来(跳过网页端或者客户端的限制和缓存)。

本文聊聊如何在 NAS 开启 SSH,并且用电脑的终端连上去。至于连上去之后能做什么,以后的文章会讲到。

NAS 开启 SSH

不管你用的是什么品牌的 NAS,开启 SSH 的核心逻辑都都差不多。

我手上只有绿联和群晖这两个品牌的 NAS,所以只介绍这两台。

绿联的话,在「控制面板 - 终端机」里启用 SSH,然后点击“应用”就能开启了。

端口可以自定义,默认是 22

在「高级设置」里面还可以设置是否允许在外网的情况下访问。

在群晖这边其实也是差不多,「控制面板 - 终端机和 SNMP」,然后勾选“启动 SSH 功能”即可。

用终端连 NAS

如果你使用 Windows 电脑,系统自带的 powershell (可以在开始菜单里面搜索)可以用 SSH 的方式连接 NAS。

macOS 的话就使用「终端」。

用法都是一样的。

ssh username@NAS_IP -p port

# 翻译过来就是
ssh 用户名@NAS的IP -p 端口(例如22)

我在内网使用,我的 NAS 的 IP 是 192.168.31.202,SSH 配置的端口是 22,所以整句命令就是 ssh 用户名@192.168.31.202 -p 22

需要注意,这里的“用户名”指的是你在 NAS 登录时用到的用户名。

首次登录的话会问你知不知道自己在干嘛,回复 yes 即可。

然后要输入密码,这里输入的密码是不会展示出来的,不管你输入什么展示的都是“空白”,但其实你按的每一个键都成功输入的。

输入的密码正确的话,就能连上 NAS 了。

连上的标志是⬇️

用户名@NAS主机名:~$

接下来就可以在终端控制 NAS 了。


以上就是本文的全部内容啦,有疑问可以在评论区讨论~

想了解更多NAS玩法可以关注《NAS邪修》👏

点赞 + 关注 + 收藏 = 学会了

 

Putty远程管理软件其实就是大家常说的 PuTTY,一个轻量级的 SSH、Telnet、串口连接工具,用来远程管理 Linux 服务器、网络设备啥的。

安装很简单,下面一步步说,保证你看完就能装上。

一、准备工作

  1. 下载安装包

    安装包下载:https://pan.quark.cn/s/d27f289a8029

  2. 确认系统位数

    • PuTTY 是绿色单文件,不分 32/64 位,Windows 都能跑。

二、安装步骤(其实是“部署”)

PuTTY 是免安装的,不用点“下一步”装到系统里,直接能用。

  1. 把下载的 Putty远程管理软件.exe放到一个固定文件夹,比如 D:\Tools\Putty

    建议别放桌面,容易误删。
  2. 双击 Putty远程管理软件.exe运行。

    • 第一次打开,Windows 可能会提示“是否允许此应用对你的设备进行更改” → 点 “是”
  3. 看到 PuTTY 主界面就说明成功了,不用额外配置。

三、首次使用(简单连个服务器)

  1. 在 “Host Name (or IP address)” 里填服务器的 IP 或域名,比如 192.168.1.100
  2. 端口默认是 22(SSH),如果是 Telnet 就改成 23。
  3. 连接类型选 SSH(常用)。
  4. Open​ 就开始连接。
  5. 第一次连会弹“安全警告” → 点 “是” ​ 接受密钥。
  6. 输入用户名和密码(Linux 下密码输入时不显示字符,正常敲完回车就行)。
  7. 登录成功,就能在黑窗口里敲命令了。

四、常用小功能

  • 保存会话:在 “Saved Sessions” 填个名字 → 点 Save,下次直接双击就能连。
  • 改字体和颜色:Window → Font settings / Colours,调成自己看着舒服的。
  • 复制粘贴:选中文字就是复制,右键就是粘贴(和平时习惯不一样,注意下)。

前言

刚好有机会接触到卫生行业的运维赛,这里只有机会接触到测试赛,简单谢谢wp吧,测试赛的话主办方也是用心了的,难度的话相比较决赛的内容还是比较简单的。

题目

【题目背景】 模拟了一台公网上的服务器,内置 MYSQL\SSH\WEB 等应用服务,但是因为安全意识不到位导致该服务器存在若干安全风险,现在要求对该服务器实施断网并作全方面的安全检查,由于服务的迁移,在系统中保留了一些历史服务的流量包,需要对流量包进行分析和研判。

【题目要求】

1、通过修改服务器登录相关的配置文件实现:密码有效期90天、连续输错三次密码,账号锁定五分钟。

2、通过修改mysql相关配置实现:开启数据库查询日志、限制任意地址登录,只允许127.0.0.1登录。

3、从 /root/analyse.pcapng 文件中分析被读取走的flag值,写到 /root/flag.txt 中。

4、对系统中存在的其他安全隐患进行排查和处置(恶意配置后门请直接删除)。

5、还有其他的一些要求,但是没在题干中

【注意事项】

1、不涉及修改密码和修改私钥的动作,如果因为修改密码或私钥导致无法得分,选手自行负责。

2、禁止使用防火墙等相关IP封锁技术对IP进行隔离,如果因为隔离IP导致无法得分,选手自行负责。

【接入信息】

1、SSH服务端口22,账号密码为root/root

2、MYSQL服务账号密码为root/mysql

步骤

登录ssh,发现处于docker容器内,其实这里很多命令是无法使用的。

先修改登录过期事件

vim /etc/login.def

PASS_MAX_DAYS 90

连续输入错误三次,锁定5分钟

vim /etc/pam.d/sshd

auth required pam_tally.so deny=3 onerr=fail unlock_time=300 #最夯一行添加配置文件

auth required pam_faillock.so preauth audit silent deny=3 unlock_time=300
auth required pam_faillock.so authfail audit deny=3 unlock_time=300

或者修改

/etc/pam.d/common-auth

隐藏后门

查看发现异常用户hacker

userdel -f hacker

这里需要强制删除,因为不添加参数的话会重新创建该用户。

访问控制

访问控制在/etc/hosts.allow中发现存在异常的访问控制,删除该文件即可

安全配置

mysql暴力破解用户名密码root/mysql

mysql -uroot -pmysql

SET GLOBAL general_log = 'ON'; //开启数据库查询日志

或者图形化界面执行修改也可以

访问控制2

限制登录地址为127.0.0.1

修改配置文件

vim /etc/mysql/mysql.conf.d/mysql.cnf

bind-address = 127.0.0.1

定时任务

这个定时任务题目有问题,没有定时任务但是需要删除root的定时任务

rm /var/spool/cron/crontabs/root

其实这里的定时任务文件是没内容的,但是check的机制就是检测文件是否存在

特殊权限

find / -type f -perm -4000 -exec ls -l {} \;

find /:从根目录开始查找(你也可以指定特定的目录,例如 /usr/bin)。

-type f:只查找文件,不查找目录。

-perm -4000:查找设置了 SUID 权限的文件(SUID 权限对应的数字是 4000)。

-ls:显示详细信息,包括文件的权限、所有者、大小、修改时间等。

所有具有suid权限的文件都在/bin下,一般whoami权限是没有suid权限的,所以这个文件被动过,所以这里干掉这个文件就可以了。

流量分析

需要开启SFTP服务,注释掉配置文件

#RSAAuthentication yes 这个配置文件是老版本openssh

另外添加ftp配置文件

Subsystem sftp internal-sftp

检索关键字,追踪tcp流分析找到一串base64编码内容

导出分组字节流解码得到flag

echo "flag{d9d2c4b2-7cf2-472f-a8e8-2aad1e466099}" > /root/flag.txt

web漏洞

目录扫描发现info目录,发现属于xxe的报错,构造xxe语句

system是可执行文件,url路径需要传参,fuzz无果手工测试

回显显示需要参数,简单测试构造发现存在任意文件读取

修复直接就是定位到位置点儿进行修复即可。其实这里最简单的就是直接代码审计,审计即可,因为前期导完数据包的时候环境有问题,修改配置文件无法SFTP连接获取源码,所以就黑盒进行FUZZ了。

用户身份认证是网络安全的重要组成部分,对用户登录尝试行为的审计,是识别可疑操作的关键环节。

登录失败通常由以下两种情况引发:

用户提供的身份凭证无效
用户不具备访问特定资源的登录权限
当用户通过 SSH 远程连接系统,或使用 su 命令切换用户身份时产生的登录失败事件,属于需要重点监控的内容。这类事件可能预示着有人正在尝试非法入侵系统。

本文将详细介绍查看 SSH 登录失败记录的具体方法。

查看 SSH 登录失败记录的操作步骤

可插拔认证模块(PAM)会记录此类身份认证事件,借助模块生成的日志,能够有效识别恶意登录行为与异常访问操作。

以下是一则登录失败的日志示例:

pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.0.2.2

        Failed password for invalid user robert from 10.0.2.2 port 4791 ssh2
        pam_unix(sshd:auth): check pass; user unknown
        PAM service(sshd) ignoring max retries; 6 > 3

为了高效排查问题,管理员需要快速定位所有此类关键登录事件,并采取对应的处置措施。

下文列出了查询所有 SSH 登录失败记录的操作步骤:

列出所有 SSH 登录失败记录的基础命令:

grep "Failed password" /var/log/auth.log

也可以通过 cat 命令实现相同效果:

cat /var/log/auth.log | grep "Failed password"

如需显示 SSH 登录失败的更多相关信息,可执行以下命令:

egrep "Failed|Failure" /var/log/auth.log

如需列出所有尝试登录 SSH 服务器但失败的客户端 IP 地址,可执行以下命令:

grep "Failed password" /var/log/auth.log | awk '{print $11}' | uniq -c | sort -nr

尽管分析上述事件的操作看似简单,但手动执行所有相关步骤耗时又费力。借助专业的日志管理解决方案,能够更便捷地分析 SSH 登录失败尝试行为。