<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Stack · Nhân Tài Đức</title>
    <link>https://jared.lynskey.co.nz/vi/tags/stack/</link>
    <description>Những câu chuyện ngắn về kỹ thuật phần mềm và lãnh đạo đội ngũ kỹ sư — performance review, tuyển dụng và mở rộng team, CI/CD, giám sát DevOps và AI agent. Viết từ Seoul.</description>
    <generator>Hugo</generator>
    <language>vi</language>
    <copyright>© 2026 Nhân Tài Đức</copyright>
    <lastBuildDate>Wed, 28 Oct 2026 00:00:00 +1300</lastBuildDate>
    <atom:link href="https://jared.lynskey.co.nz/vi/tags/stack/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Thông báo đăng nhập SSH qua Slack bằng PAM và webhook</title>
      <link>https://jared.lynskey.co.nz/vi/posts/2021/2021-12-14-ssh-log/</link>
      <guid isPermaLink="true">https://jared.lynskey.co.nz/vi/posts/2021/2021-12-14-ssh-log/</guid>
      <pubDate>Tue, 14 Dec 2021 11:30:03 +0000</pubDate>
      <dc:creator>Jared Lynskey</dc:creator>
      <category>dev</category>
      <category>full</category>
      <category>stack</category>
      <category>useful</category>
      <category>slack</category>
      <category>ssh</category>
      <category>proactive</category>
      <category>ops</category>
      <description>Nhận thông báo đăng nhập SSH trên Slack: dùng PAM và incoming webhook của Slack để biết ngay khi có người thử SSH vào máy chủ, kèm tuỳ chọn báo cả những lần đăng nhập thành công.</description>
      <content:encoded><![CDATA[
<h2 class="relative group">Mục đích
    <div id="mục-đích" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#m%e1%bb%a5c-%c4%91%c3%adch" aria-label="Cọc dấu">#</a>
    </span>
    
</h2>
<ul>
<li>Với SSH, bạn có thể cho chạy lệnh mỗi khi có người thử đăng nhập. Bài này hướng dẫn cách kết nối với Slack và điều khiển thứ tự thực thi của ssh</li>
</ul>

<h2 class="relative group">Webhook trên Slack API
    <div id="webhook-trên-slack-api" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#webhook-tr%c3%aan-slack-api" aria-label="Cọc dấu">#</a>
    </span>
    
</h2>
<ul>
<li>
<p>Xem hướng dẫn tạo ứng dụng <a href="https://api.slack.com/messaging/webhooks"  target="_blank" rel="noreferrer">tại đây</a>.</p>
</li>
<li>
<p>Bạn cần tạo một Slack app, bật webhook rồi tạo một incoming webhook để Slack nhận được thông báo từ SSH.</p>
</li>
</ul>

<h2 class="relative group">Viết script cho lần đăng nhập thất bại
    <div id="viết-script-cho-lần-đăng-nhập-thất-bại" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#vi%e1%ba%bft-script-cho-l%e1%ba%a7n-%c4%91%c4%83ng-nh%e1%ba%adp-th%e1%ba%a5t-b%e1%ba%a1i" aria-label="Cọc dấu">#</a>
    </span>
    
</h2>
<ul>
<li>Bạn có thể lưu tệp dưới đây ở bất cứ đâu trên hệ thống, tôi thì để ở <code>/var/opt/notify-attempt.sh</code></li>
</ul>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">#!/bin/bash
</span></span><span class="line"><span class="cl">if [ &#34;$PAM_TYPE&#34; != &#34;close_session&#34; ]; then
</span></span><span class="line"><span class="cl">        url=&#34;&lt;YOUR SLACK WEBHOOK&gt;&#34;
</span></span><span class="line"><span class="cl">        channel=&#34;#channel&#34;
</span></span><span class="line"><span class="cl">        host=&#34;$(hostname)&#34;
</span></span><span class="line"><span class="cl">        content=&#34;\&#34;attachments\&#34;: [ { \&#34;mrkdwn_in\&#34;: [\&#34;text\&#34;, \&#34;fallback\&#34;], \&#34;fallback\&#34;: \&#34;SSH login: $PAM_USER connected to \`$host\`\&#34;, \&#34;text\&#34;: \&#34;SSH login to \`$host\`\&#34;, \&#34;fields\&#34;: [ { \&#34;title\&#34;: \&#34;User\&#34;, \&#34;value\&#34;: \&#34;$PAM_USER\&#34;, \&#34;short\&#34;: true }, { \&#34;title\&#34;: \&#34;IP Address\&#34;, \&#34;value\&#34;: \&#34;$PAM_RHOST\&#34;, \&#34;short\&#34;: true } ], \&#34;color\&#34;: \&#34;#F35A00\&#34; } ]&#34;
</span></span><span class="line"><span class="cl">        curl -X POST --data-urlencode &#34;payload={\&#34;channel\&#34;: \&#34;$channel\&#34;, \&#34;mrkdwn\&#34;: true, \&#34;username\&#34;: \&#34;SSH Notifications\&#34;, $content, \&#34;icon_emoji\&#34;: \&#34;:inbox-tray:\&#34;}&#34; &#34;$url&#34; &amp;
</span></span><span class="line"><span class="cl">fi
</span></span><span class="line"><span class="cl">exit</span></span></code></pre></div></div>

<h3 class="relative group">Với các sự kiện SSH khác
    <div id="với-các-sự-kiện-ssh-khác" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#v%e1%bb%9bi-c%c3%a1c-s%e1%bb%b1-ki%e1%bb%87n-ssh-kh%c3%a1c" aria-label="Cọc dấu">#</a>
    </span>
    
</h3>
<ul>
<li>Với các sự kiện khác, chẳng hạn đăng nhập thành công, tôi khuyên bạn nên tạo hai tệp riêng.</li>
<li>Mỗi tệp chứa nội dung JSON tương ứng để gửi lên Slack.</li>
<li>Bạn sẽ cần sửa dòng <code>fallback\&quot;: \&quot;SSH login: $PAM_USER connected to \</code>$host`&quot;`</li>
<li>Ngay bên dưới là chỗ Openssh gọi các script này</li>
</ul>

<h3 class="relative group">Cấu hình ssh
    <div id="cấu-hình-ssh" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#c%e1%ba%a5u-h%c3%acnh-ssh" aria-label="Cọc dấu">#</a>
    </span>
    
</h3>
<p>Tôi đã thêm dấu <code>#</code> để vô hiệu hoá (comment out) dòng gửi thông báo khi đăng nhập thành công; muốn dùng thì bạn bỏ dấu <code>#</code> đi để script chạy và báo lên Slack.
Dòng này:<code># auth  optional            pam_exec.so /var/opt/notify-login.sh</code></p>
<p>[success=2] nghĩa là nếu đăng nhập ssh thành công thì sẽ nhảy qua hai dòng, tức là bỏ qua phần thông báo đăng nhập thất bại.</p>
<p>Tệp: <code>/etc/pam.d/common-auth</code></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># /etc/pam.d/common-auth - authentication settings common to all services
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># This file is included from other service-specific PAM config files,
</span></span><span class="line"><span class="cl"># and should contain a list of the authentication modules that define
</span></span><span class="line"><span class="cl"># the central authentication scheme for use on the system
</span></span><span class="line"><span class="cl"># (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
</span></span><span class="line"><span class="cl"># traditional Unix authentication mechanisms.
</span></span><span class="line"><span class="cl">#
</span></span><span class="line"><span class="cl"># As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
</span></span><span class="line"><span class="cl"># To take advantage of this, it is recommended that you configure any
</span></span><span class="line"><span class="cl"># local modules either before or after the default block, and use
</span></span><span class="line"><span class="cl"># pam-auth-update to manage selection of other modules. See
</span></span><span class="line"><span class="cl"># pam-auth-update(8) for details.
</span></span><span class="line"><span class="cl"># here are the per-package modules (the &#34;Primary&#34; block)
</span></span><span class="line"><span class="cl">auth  [success=2 default=ignore]   pam_unix.so nullok
</span></span><span class="line"><span class="cl">auth  optional            pam_exec.so /var/opt/notify-attempt.sh
</span></span><span class="line"><span class="cl"># here&#39;s the fallback if no module succeeds
</span></span><span class="line"><span class="cl">auth  requisite            pam_deny.so
</span></span><span class="line"><span class="cl"># prime the stack with a positive return value if there isn&#39;t one already;
</span></span><span class="line"><span class="cl"># this avoids us returning an error just because nothing sets a success code
</span></span><span class="line"><span class="cl"># since the modules above will each just jump around
</span></span><span class="line"><span class="cl"># For successful login, uncomment the below line, ensure the file exists.
</span></span><span class="line"><span class="cl"># auth  optional            pam_exec.so /var/opt/notify-login.sh
</span></span><span class="line"><span class="cl"># auth  required            pam_permit.so
</span></span><span class="line"><span class="cl"># and here are more per-package modules (the &#34;Additional&#34; block)
</span></span><span class="line"><span class="cl">auth  optional            pam_cap.so
</span></span><span class="line"><span class="cl"># end of pam-auth-update config</span></span></code></pre></div></div>

<h2 class="relative group">Cảm ơn bạn!
    <div id="cảm-ơn-bạn" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#c%e1%ba%a3m-%c6%a1n-b%e1%ba%a1n" aria-label="Cọc dấu">#</a>
    </span>
    
</h2>
<ul>
<li>Nếu có câu hỏi hay góp ý gì, bạn cứ liên hệ trực tiếp với tôi nhé</li>
</ul>
]]></content:encoded>
      <media:content url="https://jared.lynskey.co.nz/en/posts/2021/2021-12-14-ssh-log/featured.jpeg" medium="image" type="image/jpeg" />
    </item>
  </channel>
</rss>
