Raspberry Pi (Linux)

正規サイトとハニーポット切り替え詳細

4月2日より、「深淵 迎賓館 仕様変更」、「シュレディンガーのサーバー
の内容にてサーバー公開を行っているが、その後 iptables の改良を重ね、構成がほぼFIXしたため、その内容を覚書として記す。

●本構成の振り分けイメージ

Internet
   |
   v
+----------------------------+
|        Router              |
|     iptables / NAT         |
+----------------------------+
   |                      |
   |                      |
 Normal                 Suspicious
 / Allowed              / Unknown
   |                      |
   v                      v
+----------------+   +----------------+
| 192.168.1.1    |   | 192.168.1.2    |
| Main Server    |   | Honeypot       |
+----------------+   +----------------+

上記の振り分けを、PREROUTINGチェインに集約した。
現在はPREROUTINGを確認するだけで、流入トラフィックの性質がほぼ把握できる状態となっている。

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       44  2492 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set firehol_level3 src to:192.168.1.2:25
2        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set firehol_level2 src to:192.168.1.2:25
3        5   228 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set firehol_level1 src to:192.168.1.2:25
4        2   120 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set gcloud src to:192.168.1.2:25
5        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set other_block src to:192.168.1.2:25
6      126  6626 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set firehol_level3 src to:192.168.1.2:80
7       50  2592 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set firehol_level2 src to:192.168.1.2:80
8       12   580 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set firehol_level1 src to:192.168.1.2:80
9        2   100 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set gcloud src to:192.168.1.2:80
10       0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set other_block src to:192.168.1.2:80
11     255 13436 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set firehol_level3 src to:192.168.1.2:443
12      15   784 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set firehol_level2 src to:192.168.1.2:443
13      17   920 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set firehol_level1 src to:192.168.1.2:443
14       4   200 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set gcloud src to:192.168.1.2:443
15       0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set other_block src to:192.168.1.2:443
16      13   760 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:ssh match-set jpnet src to:192.168.1.1:22
17       1    60 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set jpnet src to:192.168.1.1:25
18       0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp match-set searchengines src to:192.168.1.1:25
19       1    40 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set jpnet src to:192.168.1.1:80
20       3   180 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set searchengines src to:192.168.1.1:80
21      16   988 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set jpnet src to:192.168.1.1:443
22     176  9872 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set searchengines src to:192.168.1.1:443
23       0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:submission match-set jpnet src to:192.168.1.1:587
24       1    60 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:imaps match-set jpnet src to:192.168.1.1:993
25       7   356 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp to:192.168.1.2:25
26     150  7602 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http to:192.168.1.2:80
27     305 18288 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https to:192.168.1.2:443
28       8   480 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:2222 match-set jpnet src to:192.168.1.2:22

・firehol_level1~3 : FireHOLで公開されているブラックリストIPからのアクセスを Honeypot(192.168.1.2)へ振り分け
・jpnet : 日本国内からのアクセスを Main Server(192.168.1.1)へ振り分け
・searchengines : 主要サーチエンジンからのアクセスを Main Server(192.168.1.1)へ振り分け
・gcloud : スパムアクセスの多い Google Cloud からのアクセスを Honeypot(192.168.1.2)へ振り分け
・other_block : その他、不審と判断したアクセス(主に国内)を Honeypot(192.168.1.2)へ振り分け

Hugoへ移行しての所感

当サイトのブログをHugoへ移行して10日ほど経過し、テーマも最終の形態に落ち着いてきた。
サイトの使い勝手や見た目もblogn時代と比べ無駄を排除した上でかなり向上した。
特にphpの処理が無いため、記事数の多いweblogでも瞬時に表示される。
以前、weblogを記事数2935で公開していた時は、表示されるまでに2秒近くかかっていた。

もう一点、運用面で大きいのは精神的な負担が減ったことだ。
phpやDB、CMSの脆弱性を気にする必要がなく、壊れないものを淡々と置いておく感覚に近い。
個人ブログとしては、これが一番のメリットかもしれない。

また、Raspberry Pi上での運用という点でも、Hugoの相性は非常に良い。
ビルドは別環境で行い、サーバー側は単なる静的ファイル置き場として振る舞うだけなので、CPU負荷やメモリ使用量をほとんど気にしなくて済む。

Hugoへ移行して気になる点といえば、やはり投稿時の手間と、サーバー側ディスクの負担増である。
記事一点を追加する度にブログ全体をビルドして全ファイル差し替えとなるため、例えば本ブログ(retiredlog)の場合、下記ディスク占有容量である5.3Mバイト以上の書き換えが必要となる。
これは、記事数が増えればそれに伴い増加していく。

retiredlog
記事数 88
pagefind 1.3Mバイト
ディスク占有容量 5.3Mバイト

もっとも、ディスク容量については記事数が数千規模になっても数百MB程度で収まる見込みであり、現実的には大きな問題にはならないだろう。
むしろ速度と単純さを優先した結果として、納得して受け入れている。

なお、写真やファイルについては、転送容量とディスク書き込み負担軽減のため、毎回全ファイルを転送する訳ではなく、サーバー側で別途ファイル専用ディレクトリーを用意して、下記(files)のようにシンボリックリンクを張っている。

/mnt/data/sky/retiredlog
合計 352
drwxr-xr-x 11 pi pi 4096 1月 29 06:51 .
drwxr-xr-x 14 pi pi 4096 1月 26 20:03 ..
-rw-r–r– 1 pi pi 8863 1月 31 15:23 404.html
-rw-r–r– 1 pi pi 111 1月 18 07:19 apple-touch-icon.png
drwxr-xr-x 2 pi pi 4096 1月 20 20:22 archives
drwxr-xr-x 8 pi pi 4096 1月 18 07:49 categories
drwxr-xr-x 2 pi pi 4096 1月 24 07:35 css
-rw-r–r– 1 pi pi 16958 10月 11 15:24 favicon.ico
lrwxrwxrwx 1 pi pi 41 1月 26 13:18 files -> /mnt/data/sky/blog_data/retiredlog/files/
drwxr-xr-x 2 pi pi 4096 1月 18 07:49 img
-rw-r–r– 1 pi pi 44360 1月 31 15:23 index.html
-rw-r–r– 1 pi pi 213825 1月 31 15:23 index.xml
drwxr-xr-x 2 pi pi 4096 1月 18 07:49 js
drwxr-xr-x 20 pi pi 4096 1月 30 13:38 page
drwxr-xr-x 4 pi pi 4096 1月 31 14:38 pagefind
drwxr-xr-x 89 pi pi 4096 1月 30 14:59 posts
-rw-r–r– 1 pi pi 12890 1月 31 15:23 sitemap.xml
drwxr-xr-x 3 pi pi 4096 1月 24 07:35 tags

Hugoテーマ Mainroad 改善

今日は朝から冷え込んで、路面にはうっすらと雪が積もっている。
こんな日は外に出ず、暖かい部屋でゆっくり過ごすに限る。

暇な日曜日の時間つぶしとして、このブログのHugoテーマ「Mainroad」の改善に着手した。
デザインは気に入っているが、一点だけ不便を感じていた「個別記事ページでの前後ナビゲーション」を追加することにする。

以下、自分用の備忘録を兼ねたカスタマイズ手順だ。

  1. 個別記事に「過去記事・未来記事」ボタンを追加

Mainroadの layouts/_default/single.html を編集し、記事のヘッダー部分にナビゲーションを配置した。
blogn時代のように、記事の冒頭で前後の流れを確認できるようにしている。

<nav class="post-nav flex">
    {{ with .PrevInSection }}
    <div class="post-nav__item post-nav__item--prev">
        <a class="post-nav__link" href="{{ .RelPermalink }}" rel="prev">
            <span class="post-nav__caption">≪&nbsp;過去の記事</span>
            <p class="post-nav__post-title">{{ .Title }}</p>
        </a>
    </div>
    {{ end }}
    {{ with .NextInSection }}
    <div class="post-nav__item post-nav__item--next">
        <a class="post-nav__link" href="{{ .RelPermalink }}" rel="next">
            <span class="post-nav__caption">新しい記事&nbsp;≫</span>
            <p class="post-nav__post-title">{{ .Title }}</p>
        </a>
    </div>
    {{ end }}
</nav>
  1. メタ情報の整理(日付とカテゴリー)

境界線が二重にならないよう、テーマ標準の post_meta.html を活かしつつ、hugo.toml で表示を制御。
これで日付とカテゴリーがスッキリ一行に収まった。

[Params]
post_meta = [“date”, “categories”]

トップページへ戻るボタン追加

早起きは暇の元(笑)
土日は相変わらず暇だし・・・ということで、またhugoネタ。

分割ビューやアーカイブリストなど、順次下の方を閲覧したところでトップページに戻る場合、上にスクロールしてサイトタイトルをクリックする必要があった。
これはかなり不便なので、フッターに「トップページへ戻る」ボタン追加。

下記はその忘備録。
1). layouts\partials\footer.html

<footer class="footer">
	<div class="container footer__container flex">
		{{ partial "footer_links.html" . }}
		<div class="footer__copyright">
			&copy; {{ now.Format "2006" }} {{ .Site.Params.copyright | default .Site.Title }}.
			<span class="footer__copyright-credits">{{ T "footer_credits" | safeHTML }}</span>
		</div>
		/* 以下を追加 */
		<div class="footer-home-nav">
			<a href="/" class="home-button">トップページへ戻る</a>
		</div>
		
	</div>
</footer>

2). static\css\custom.css

以下を末尾に追加

/* ===== Home Button Style ===== */
.footer-home-nav {
  text-align: center;      /* 中央寄せ */
  margin: 5px 0 5px;     /* 上下に余白をとる */
  padding: 0px;
}

.home-button {
  display: inline-block !important;
  background-color: #333 !important; /* ボタンの色(白ベースなら赤 #e22d30 もおすすめ) */
  color: #ffffff !important;         /* 文字色(白) */
  padding: 10px 20px !important;    /* 押しやすいように大きめに */
  text-decoration: none !important;  /* 下線を消す */
  border-radius: 50px !important;    /* 角を丸くしてボタンらしく */
  font-weight: bold !important;
  font-size: 1.1rem !important;
  box-shadow: 0 4px 6px rgba(0,0,0,0.2); /* 少し浮かせて「押せる感」を出す */
  transition: transform 0.2s, background-color 0.2s;
}

.home-button:hover {
  background-color: #7aa2ff !important; /* ホバー時は青系に */
  transform: translateY(-2px);           /* 軽く浮き上がる演出 */
  color: #ffffff !important;
}

Mainroad ダークモードセットアップ

以前、blognでブログを運用していた頃も、最終的には背景がブラックのダークモードで落ち着いていた。
Hugo + Mainroad に移行後はホワイトベースがデフォルトだったが、やはり自分にはダーク系の方がしっくりくる。

今日は株取引の日でもあるのだが、相場を眺めていると、たまに阿保らしくなってくる(笑)

そこで今日は、相場チェックはそこそこにして、AIに相談しながら Mainroad のダークモード化をセットアップしてみた。

変更点は custom.css のみ。
テーマ本体には一切手を入れていない。

下記はその具体内容

● サイトをダーク系配色にする場合の custom.css 追記分
/static/css/custom.css

/* ===== Mainroad Dark Base ===== */
html, body, .container, .wrapper, .main, .sidebar, .post, .widget {
  background: #202020 !important;
  color: #d6d6d6 !important;
}

/* サイトタイトル・本文 */
.logo a, p, li {
  color: #d6d6d6 !important;
}

/* 見出し */
h1, h2, h3, h4, h5, h6 {
  color: #e6e6e6 !important;
}

/* リンク */
a {
  color: #7aa2ff !important;
}

a:hover {
  color: #a5c0ff !important;
}
/* ウィジェットタイトル下のライン:少し暗くして馴染ませる */
.widget__title {
  border-bottom: 2px solid #444 !important; /* #cccから変更 */
}

/* コードブロック:背景を少しだけ明るくして認識しやすくする */
pre, code {
  background: #2b2b2b !important; /* 全体背景より少し明るいグレー */
  color: #e6e6e6 !important;
  padding: 0.2em 0.4em;
  border-radius: 3px;
}
/* ===== Header & Titles ===== */

.header, .header * {
  color: #ADDFB3 !important;
}

.header svg {
  fill: currentColor;
}

.post__title, .post__title a {
  color: #90D7EC !important;
}
/* ===== Search Widget (Final Optimized) ===== */
/* 1. 検索フォーム全体の枠組み */
.widget-search__form {
  display: flex !important;
  background: #202020 !important;
  align-items: stretch !important;
  border: none !important;
}

/* 2. 入力欄(テキストボックス) */
.widget-search__field {
  flex-grow: 1 !important;
  background: #2b2b2b !important;
  color: #d6d6d6 !important;
  border: 1px solid #444 !important;
  border-radius: 4px 0 0 4px !important;
  padding: 10px !important;
  outline: none;
}

/* プレースホルダー(Search...の文字) */
.widget-search__field::placeholder {
  color: #888 !important;
}

/* 3. 検索ボタン */
.widget-search__submit {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: 60px !important;       /* 幅をスリムに固定 */
  min-width: 40px !important;
  padding: 0 !important;
  flex-shrink: 0 !important;
  background-color: #444 !important;
  fill: #ffffff !important;
  color: #ffffff !important;
  border: none !important;
  border-radius: 0 4px 4px 0 !important;
  margin-left: -1px !important;
  cursor: pointer;
  transition: background-color 0.2s;
}

/* 4. マウスを乗せた時の反応 */
.widget-search__submit:hover {
  background-color: #7aa2ff !important;
}