Python3+FlaskでShift_JISのWEBサーバーを立てる

・ python3: 3.11.2
・ python3-flask: 2.2.2

Shift_JISのWEBサーバーに対するリクエストテストをしたくて、Pythonで簡単に書いたときの備忘録です。自分では絶対に作らない環境なので、また使いそう。

from flask import Flask, request, Response
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def handler():
    value_of_post = request.form.get("param1")
    value_of_get = request.args.get("param2")
    print(value_of_post)
    print(value_of_get)
    response_text = ("Received param: " + str(value_of_post) + ", " + str(value_of_get)).encode("shift_jis")
    response = Response(response_text, content_type="text/plain; charset=shift_jis")
    return response
if __name__ == "__main__":
    app.run(debug=True)

Linuxで特定のポートを使用しているプロセスを特定する

ポートの競合が起きる場合などのトラブルシューティングに使える。
※”lsof”は”list open files”の略らしい
※下記は22番ポートを使用しているプロセスを表示する

# lsof -i:22

特定のリッスンポートに一致するプロセスを表示する。
※-lオプションはリッスン状態のソケットだけを表示
※-nオプションはサービス名ではなくポート番号を表示
※-pオプションはプロセスの情報を表示

ss -lnp | grep 3000

AlmaLinux9をドメイン参加させてファイルサーバーにする

環境

ここの手順で構築したドメインコントローラーで認証する。

・ AlmaLinuxのバージョン: 9.4
・ ホスト名: samba.ad.example.jp
・ IPアドレス: 192.168.1.13
・ realmdのバージョン: 0.17.1
・ sambaのバージョン: 4.19.4

FQDNでホスト名を設定する。

# hostnamectl set-hostname samba.ad.example.jp

必要なパッケージをインストールする。

# dnf install realmd samba

参照するDNSをドメインコントローラーに変更する。

# nmcli connection modify [コネクションID] ipv4.dns [ドメインコントローラーのIPアドレス]
# nmcli connection up [コネクションID]

smb.confをバックアップする。

# mv /etc/samba/smb.conf /etc/samba/smb.conf.backup

ドメインコントローラーにjoinする。
※ドメインのメンバーとして機能するためのソフトウェアにsambaを指定
※ドメインユーザーの認証を処理するソフトウェアにwinbindを指定

# realm join --membership-software=samba --client-software=winbind AD.EXAMPLE.JP

共有ディレクトリを作成する。
※root以外がアクセスできないようにする

# mkdir -p /data/samba/share
# chmod 770 /data/samba/share

初期設定されたsambaの設定ファイルを編集して最下行に追記する。
※「force user」にrootを指定してファイル操作をrootで実行させる

[share]
path = /data/samba/share
create mask = 0660
directory mask = 0770
force user = root
writable = yes
valid users = @"example\domain users" "example\administrator"

ファイアウォールに例外を登録する。

# firewall-cmd --permanent --add-service=samba
# firewall-cmd --reload

SELinuxのラベル付けを行う。

# semanage fcontext -a -t samba_share_t "/data/samba/share(/.*)?"
# restorecon -RF /data/samba/share/

SELinuxにsmbdによるパブリックディレクトリへの書き込みを有効にする。

# setsebool -P allow_smbd_anon_write true

サービスを有効にして起動する。

# systemctl enable --now smb

Ubuntu22.04をドメイン参加してxrdpで接続する

前提条件

※ドメインコントローラーのIPは192.168.1.11
※クライアントのFQDNはclient.ad.example.jp

・ Ubuntu: 22.04.4
・ realmd: 0.17.0

DNSをドメインコントローラーにする。

# nmcli connection modify [接続名] ipv4.dns 192.168.1.11

ホスト名をFQDNにしておく。

# hostnamectl set-hostname client.ad.example.jp

ドメインに参加するためのパッケージをインストールする。

# apt install realmd

参加するドメインを確認する。

# realm discover AD.EXAMPLE.JP

ドメインに参加する。

# realm join AD.EXAMPLE.JP

xrdpをインストール、有効化して起動する。

# apt install xrdp
# systemctl enable --now xrdp

このままでもGUIログインやsshでのログインは問題ないが、xrdpにドメインユーザーで認証することができなかったので設定ファイルを2箇所変更した。

…
# ドメイン名を省略してログイン
# xrdpはデフォルトでドメイン名を解釈してくれない
#use_fully_qualified_names = True
use_fully_qualified_names = False
…
# xrdpセッションマネージャーのサービス名を指定
ad_gpo_map_remote_interactive = +xrdp-sesman

sssdを再起動する。

# systemctl restart sssd

AlmaLinux9でdhcpとbindを連携させ家庭内DDNS

DNSサーバーもDHCPサーバーも1台で兼任させるが、冗長化のためゾーン転送を利用して2台分を設定する。

・ AlmaLinux: 9.4
・ bind: 9.16.23
・ dhcp-server: 4.4.2
・ プライマリIPアドレス: 192.168.1.11
・ セカンダリIPアドレス: 192.168.1.12

プライマリサーバーの設定

パッケージをインストールする。

# dnf install bind dhcp-server

DNSサーバーの設定ファイルを変更または追記する。

options {
    listen-on port 53 { any; };
    listen-on-v6 { none; };
    directory "/var/named/";
    …
    // LAN内からの問い合わせを許可
    allow-query {
        localhost;
        192.168.1.0/24;
    };
    …
    // ゾーン転送を許可するIPを設定
    allow-transfer {
        192.168.1.12;
    };
    // 自分で名前解決できないときの丸投げ先
    forwarders {
        192.168.1.254;
        8.8.8.8;
    };
};
…
zone "example.jp." {
    type master;
    file "example.jp.zone";
    // 自身からの変更を許可
    allow-update {
        localhost;
        192.168.1.12;
    };
};
…

さっき指定したzoneファイルを作成する。
※LAN内のDDNSに使用するため更新間隔を短く
※”admin.example.jp.”は”admin@example.jp”という管理者のE-mailという意味らしい

$TTL 86400
@    IN    SOA    sv1.example.jp.    admin.example.jp. (
           2024071501
           300
           60
           3600
           300
)

        IN    NS   sv1.example.jp.
        IN    NS   sv2.example.jp.
sv1     IN    A    192.168.1.11
sv2     IN    A    192.168.1.12

作成したらファイルの所有者をnamedに変更する。

# chown named:named /var/named/example.jp.zone

DHCPサーバーの設定ファイルに下記を追記する。

# DNSサーバーに更新要求を送信する設定
ddns-update-style interim;
# 普通のDHCPの設定
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.101 192.168.1.120;
    option routers 192.168.1.254;
    option domain-name "example.jp";
    option domain-name-servers 192.168.1.11, 192.168.1.12;
    # 更新を通知するDNSサーバーを指定
    zone example.jp. {
        primary localhost;
    }
}

SELinuxとファイアウォールに例外を追加する。

# setsebool -P named_write_master_zones true
# firewall-cmd --add-service=dns --permanent
# firewall-cmd --add-service=dhcp --permanent
# firewall-cmd --reload

サービスを有効にして起動。

# systemctl enable --now named
# systemctl enable --now dhcpd

セカンダリサーバーの設定

パッケージをインストールする。

# dnf install bind dhcp-server

DNSサーバーの設定ファイルを変更または追記する。

options {
    listen-on port 53 { any; };
    listen-on-v6 { none; };
    directory "/var/named/";
    …
    allow-query {
        localhost;
        192.168.1.0/24;
    };
    …
    forwarders {
        192.168.1.254;
        8.8.8.8;
    };
};
…
zone "example.jp." {
    type slave;
    file "example.jp.zone";
    masters {
        192.168.1.11;
    };
};
…

DHCPサーバーの設定ファイルに下記を追記する。

ddns-update-style interim;
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.121 192.168.1.140;
    option routers 192.168.1.254;
    option domain-name "example.jp";
    option domain-name-servers 192.168.1.11, 192.168.1.12;
    zone example.jp. {
        primary 192.168.1.11;
    }
}

SELinuxとファイアウォールに例外を追加する。

# firewall-cmd --add-service=dns --permanent
# firewall-cmd --add-service=dhcp --permanent
# firewall-cmd --reload

サービスを有効にして起動。

# systemctl enable --now named
# systemctl enable --now dhcpd

補足

ゾーンを再読み込みする

保持しているゾーンの情報をリロードする。mastersのシリアルが保持しているシリアルよりも大きければゾーン転送が行われる。

# rndc reload example.jp
現在のDNSレコードの確認

rndcでdumpして現在のDNSレコードを確認する。

# rndc dumpdb -zones
# less /var/named/data/cache_dump.db 
DNSレコードの更新テスト

nsupdateを使用してDNSサーバーを更新をテストするにはbind-utilsをインストールし、nsupdateコマンドを実行する。実行したら対話型コンソールになるので下記のような感じで入力する。何もエラーが出なければOK。
※INはインターネットの意味らしいが未指定でも問題ない

>server 127.0.0.1
>update add test.example.jp. 3600 IN A 192.168.1.222
>send
>server 127.0.0.1
>update delete test.example.jp. IN
>send
DNSレコードの削除

まれにDNSレコードのIPアドレスが一切更新されなくなるクライアントがある。nsupdateコマンドを実行して古いDNSレコードを削除するとそのうち直る。

>server 127.0.0.1
>update delete test.example.jp.
>send

Ubuntu22.04でdhcpとbindを連携させ家庭内DDNS

DNS(ddns.example.jp)サーバーもDHCPサーバーも1台で兼任させる。ActiveDirectory(ad.example.jp)に関するクエリはドメインコントローラーにフォワードさせる。

・ Ubuntu: 22.04.4
・ bind: 9.13.6
・ isc-dhcp-server: 4.4.1

DNSサーバーの設定

bindから設定、パッケージをインストールする。

# apt install bind9

オプション設定ファイルを変更または追記する。

options {
    directory "/var/cache/bind";
    …
    // 自分で名前解決できないときの丸投げ先
    forwarders {
        192.168.1.254;
        8.8.8.8;
    };
    …
    // DNSSECを自動に設定してDCへのフォワードは除外
    dnssec-validation auto;
    validate-except {
        "ad.example.jp";
    };
    …
    // IPv6を無効化
    listen-on-v6 { none; };
    …
    // LAN内からの問い合わせを許可
    allow-query {
        localhost;
        192.168.1.0/24;
    };
};

ローカル設定ファイルに追記する。

zone "ddns.example.jp." {
    type master;
    file "ddns.example.jp.zone";
    // 自身からの変更を許可
    allow-update {
        localhost;
    };
};
zone "ad.example.jp." {
    type forward;
    forward only;
    forwarders {
        192.168.1.12;
    };
};

さっき指定したzoneファイルを作成する。
※”admin.ddns.example.jp.”は”admin@ddns.example.jp”という管理者のE-mailという意味らしい

$TTL 86400
@    IN    SOA    sv.ddns.example.jp.    admin.ddns.example.jp. (
           2024071501
           10800
           36400
           604800
           86400
)

        IN    NS   sv.ddns.example.jp.
sv      IN    A    192.168.1.11

作成したらファイルの所有者をbindに変更する。

# chown bind:bind /var/cache/bind/ddns.example.jp.zone

サービスを有効にして起動。

# systemctl enable --now named

DHCPサーバーの設定

パッケージをインストールする。

# apt install isc-dhcp-server

設定ファイルで下記の箇所を変更する。

…
# DNSサーバーに更新要求を送信する設定
ddns-update-style interim;
…
# 普通のDHCPの設定
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.101 192.168.1.120;
    option routers 192.168.1.254;
    option domain-name "ddns.example.jp";
    option domain-name-servers 192.168.1.11;
    # 更新を通知するDNSサーバーを指定
    zone ddns.example.jp. {
        primary localhost;
    }
}

サービスを有効にして起動。

# systemctl enable --now isc-dhcp-server

補足

現在のDNSレコードの確認

rndcでdumpして現在のDNSレコードを確認する。

# rndc dumpdb -zones
# less /var/cache/bind/named_dump.db
DNSレコードの更新テスト

nsupdateを使用してDNSサーバーを更新をテストするにはbind-utilsをインストールし、nsupdateコマンドを実行する。実行したら対話型コンソールになるので下記のような感じで入力する。何もエラーが出なければOK。
※INはインターネットの意味らしいが未指定でも問題ない

>server 127.0.0.1
>update add test.ddns.example.jp. 3600 IN A 192.168.1.222
>send
>server 127.0.0.1
>update delete test.ddns.example.jp. IN
>send
DNSレコードの削除

まれにDNSレコードのIPアドレスが一切更新されなくなるクライアントがある。nsupdateコマンドを実行して古いDNSレコードを削除するとそのうち直る。

>server 127.0.0.1
>update delete test.example.jp.
>send

Ubuntu22.04でActiveDirectoryを構築してファイル共有もする

前提条件

※プライマリ(192.168.1.11)とセカンダリ(192.168.1.12)の2台を設定
※ddnsは別のbindサーバーが担うので設定しない
※ntpサーバーは外部のものを使うので設定しない
※プライマリのみをファイルサーバーにする

・ Ubuntu: 22.04.4
・ samba: 4.15.13

プライマリとセカンダリ共通の設定手順

ホスト名をFQDNにする。

# hostnamectl set-hostname [ホスト名].ad.example.jp

公式によると下記のパッケージが必要らしいのでインストール。

# apt install acl attr samba winbind libpam-winbind libnss-winbind krb5-config krb5-user dnsutils python3-setproctitle

samba-ad-dcサービスのマスクを解除する。

# systemctl unmask samba-ad-dc

まぎらわしいサービスを無効化する。

# systemctl disable --now smbd nmbd winbind
# systemctl mask smbd nmbd winbind

設定ファイルのバックアップを取る。

# mv /etc/samba/smb.conf /etc/samba/smb.conf.backup
# mv /etc/krb5.conf /etc/krb5.conf.backup

プライマリドメインコントローラーの設定手順

ドメインのプロビジョニングを実行する。
–-use-rfc2307 (UNIX系を認証する場合は必須)
--interactive (セットアップを対話式で行う)

# samba-tool domain provision --use-rfc2307 --interactive
----------------------------------------
Realm:  AD.EXAMPLE.JP
Domain [AD]:  EXAMPLE
Server Role (dc, member, standalone) [dc]:
DNS backend (SAMBA_INTERNAL, BIND9_FLATFILE, BIND9_DLZ, NONE) [SAMBA_INTERNAL]:
DNS forwarder IP address (write 'none' to disable forwarding) [127.0.0.53]:  8.8.8.8
Administrator password:
Retype password:
…

もし実行中に下記メッセージで停止してしまう場合は、sambaをpurgeして、/var/lib/samba/を削除して、sambaを再インストールしてからやり直す。

Repacking database from v1 to v2 format (first record CN=FileLinks,CN=System,DC=ad,DC=example,DC=jp)

できあがったkrb5.confをコピーする。

# cp /var/lib/samba/private/krb5.conf /etc/krb5.conf

samba-ad-dcサービスを有効化する。

# systemctl enable --now samba-ad-dc

systemd-resolvedがDNSサーバーの邪魔をするので無効化する。

# systemctl disable --now systemd-resolved
# rm /etc/resolv.conf

/etc/resolv.confをNetworkManagerに作らせるためmainセクションに追記する。

[main]
dns=default
…

DNSを自分自身に変更して再起動する。

# nmcli connection modify [コネクションID] ipv4.dns 127.0.0.1
# shutdown -r now

セカンダリドメインコントローラーの設定手順

参照するDNSをプライマリに変更する。

# nmcli connection modify [コネクションID] ipv4.dns 192.168.1.11
# nmcli connection up [コネクションID]

ドメインコントローラーとしてjoinする。

# samba-tool domain join ad.example.jp DC -U administrator@example

smb.confのglobalセクションに下記を追記する。

…
dns forwarder = [プライマリと同じforwarder]
idmap_ldb:use rfc2307 = yes
…

GPOが同期されないので、セカンダリ側からプライマリのGPOをコピーするスクリプトを適当に書いた。GPOの変更はプライマリに対して行う運用にして、変更後はセカンダリで下記スクリプトをrootで実行するようにする。スクリプトにはパスワード書いておくのでパーミッションは700にする。

#!/bin/bash
if [ ${EUID:-${UID}} != 0 ]; then
    echo "Please run with Root."
    exit 1
fi
mount.cifs -V 1>/dev/null 2>/dev/null
if [ ! $? -eq 0 ]; then
    echo "cifs-utils is not installed."
    exit 1;
fi
temporary="/tmp/sysvol"
dc="pdc.ad.example.jp"
domain="example";
user="administrator";
pass="password";
mkdir -p $temporary
mount.cifs -o username=$user@$domain,password=$pass,file_mode=0400,dir_mode=0500 //$dc/sysvol $temporary
if [ ! $? -eq 0 ]; then
    exit 1;
fi
cp -rf $temporary/* /var/lib/samba/sysvol/
samba-tool ntacl sysvolreset
umount $temporary

ここからプライマリと同じ手順。

# cp /var/lib/samba/private/krb5.conf /etc/krb5.conf
# systemctl enable --now samba-ad-dc
# systemctl disable --now systemd-resolved
# rm /etc/resolv.conf
# sed -i "s/\[main\]/\[main\]\ndns=default/g" /etc/NetworkManager/NetworkManager.conf
# nmcli connection modify [コネクションID] ipv4.dns 127.0.0.1
# shutdown -r now

ファイルサーバーの設定手順

共有するディレクトリを作成する。
※root以外がアクセスできないようにする

# mkdir -p /data/samba/share
# chmod 770 /data/samba/share

sambaの設定ファイルを編集して最下行に追記する。
※Linuxへの共有が目的なので「Windows ACL」はいらない
※”force user”にrootを指定してファイル操作をrootで実行させる

…
[share]
path = /data/samba/share
nt acl support = no
create mask = 0660
directory mask = 0770
force user = root
writable = yes
valid users = "example\user1" @"example\Domain Admins"

samba-ad-dcサービスを再起動する。

# systemctl restart samba-ad-dc

使いそうなコマンド

DNSレコードに登録されているLDAPとKerberosのサービスを確認できる。この手順で構築した環境で実行すると2行のレコードが表示される。

# host -t SRV _ldap._tcp.ad.example.jp.
# host -t SRV _kerberos._udp.ad.example.jp.

DNSの更新状況を確認できる。
No DNS updates needed ならOKらしい。

# samba_dnsupdate --verbose

パスワードに関するポリシーの確認と変更ができる。

# samba-tool domain passwordsettings show
# samba-tool domain passwordsettings set --complexity=off
# samba-tool domain passwordsettings set --min-pwd-length=5
# samba-tool domain passwordsettings set --min-pwd-age=30
# samba-tool domain passwordsettings set --max-pwd-age=0
# samba-tool domain passwordsettings set --account-lockout-duration=60
# samba-tool domain passwordsettings set --account-lockout-threshold=3
# samba-tool domain passwordsettings set --reset-account-lockout-after=60
# samba-tool domain passwordsettings set --history-length=5

ユーザーの新規作成、初回ログイン時にパスワードを変更させる。

# samba-tool user add user1 --must-change-at-next-login

ユーザーのロック状態を解除する。

# samba-tool user unlock user1

ユーザーのパスワードを変更して、次回ログイン時にパスワードを変更させる。

# samba-tool user setpassword user1 --must-change-at-next-login

ユーザーをグループに追加する。

# samba-tool group addmembers "Domain Admins" user1

ドメインコントローラーの降格。

# samba-tool domain demote --remove-other-dead-server=[ホスト名]

FSMOを確認できる。

# samba-tool fsmo show

FSMOの移行。転送先サーバーで下記コマンドを実行する。

# samba-tool fsmo transfer --role all

DNSレコードを確認する。

# samba-tool dns query localhost ad.example.jp. @ ALL -U Administrator

DNSレコードを削除する。まれにDNSレコードのIPアドレスが一切更新されなくなるクライアントがある。下記を実行して古いDNSレコードを削除するとそのうち直る。

# samba-tool dns delete localhost ad.example.jp. client01 A 192.168.1.222 -U Administrator

Electron+Reactでアプリを開発する

・debian 12.6
・vscode 1.89.1
・node 20.13.1
・typescript 5.4.5
・vite 5.2.12
・react 18.3.3
・electron 30.0.9

viteでプロジェクトを作成する。

$ npm create vite sample-app -- --template react-ts

electronをインストールする。

$ cd sample-app
$ npm install --save-dev electron electron-builder

electron用のディレクトリを作成する。

$ mkdir electron/

electronに必要なファイルを作成する。

プロジェクトルートにあるtsconfig.jsonに作成したディレクトリを追加する。

    …
    "include": ["src", "electron"],
    …

preload.tsに定義されたAPIの動作確認のため、App.tsxの適当な場所に下記を追記する。

    …
    <button onClick={() => { alert(window.counterAPI.count()) }}>
        counting via API
    </button>
    …

vite.config.tsに相対パスを使用する定義と、Reactのビルド出力先の定義を追記する。

…
export default defineConfig({
  plugins: [react()],
  base: "./",
  build: {
    outDir: "build/"
  }
})

package.jsonにtypeとmainを定義する。typeはデフォルトでcjsなので削除してしまっても良い。

    …
    "type": "commonjs",
    "main": "build/electron/main.js",
    …

package.jsonに開発用とビルド用のスクリプトを追記する。

    …
    "scripts": {
        …
        "electron:dev": "tsc -p electron/ && electron . & vite",
        "electron:build": "tsc && vite build && tsc -p electron/ && electron-builder --dir"
    },
    …

package.jsonにビルドに必要な情報を追記する。

    …
    "build": {
        "appId": "com.example.sample-app",
        "productName": "SampleApp",
        "files": [
            "build/**/*"
        ]
    },
    …

reactのホットリロードを利用して開発用にアプリを起動する。

$ npm run electron:dev

アプリをビルドする。

$ npm run electron:build

Windowsのbatファイルで忘れがちな書き方

tasklistコマンドを利用して設定ウィンドウが存在するか判定する。

@echo off
set windowtitle=設定
tasklist /FI "WINDOWTITLE eq %windowtitle%" | find "実行されていません" > nul
if %ERRORLEVEL% == 1 (
    echo %windowtitle%が存在します。
)
pause

batファイルで自身の多重起動を防止したい場合は下記のようにするとそれなりに防止できる。

@echo off
set windowtitle=test
tasklist /FI "WINDOWTITLE eq %windowtitle%" | find "実行されていません" > nul
if %ERRORLEVEL% == 1 (
    exit
)
title %windowtitle%
pause

taskkillコマンドを利用して設定ウィンドウを閉じる。

@echo off
set windowtitle=設定
taskkill /FI "WINDOWTITLE eq %windowtitle%"
pause