RADIUSについての解説

RADIUSについての解説

用語定義

  • RADIUS: Remote Authentication Dial-In User Serviceの略で、ネットワークアクセスサーバ(NAS)と認証サーバ間で認証、認可、アカウンティング(AAA)情報を交換するためのプロトコル
  • Radiusクライアント: NASとも呼ばれる。主にNW機器やVPN機器で認証情報をRadiusに問い合わせる
  • 共有キー: RadiusクライアントとRadiusサーバ間で共有するパスワード

RADIUSの主な設定ファイル

radiusd.conf

RADIUSの主設定ファイルで、デーモンの全般的な設定を行う。この設定ファイルには、ネットワークの設定、ロギング、スレッド、モジュールの設定などが含まれてる。RADIUSデーモンの動作をカスタマイズするためには、このファイルを編集する。

prefix = /usr/local
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
logdir = ${sysconfdir}/radacct

clients.conf

クライアントの設定を管理するファイルで、RADIUSサーバがサービスを提供するNASクライアントを定義する。各クライアントは、クライアントのIPアドレス(またはネットワーク)とRADIUSサーバとの間でパケットの整合性と認証を保証するための共有シークレットを指定する。デフォルトでは、clients.conf ファイルには特定のクライアント設定は含まれていない。必要に応じてクライアントのエントリーを追加する。

client localhost {
    ipaddr = 127.0.0.1
    secret = testing123
    require_message_authenticator = no
    nas_type = other
}

RADIUS認証方式

  • PAP: Password Authentication Protocolは、もっとも基本的なパスワードベースの認証プロトコル。この認証方式はセキュリティが弱いため、安全でないネットワークでの使用は推奨されない。

  • CHAP: Challenge-Handshake Authentication Protocolは、PAPよりもセキュリティが強化された認証方式。CHAPはパスワードを平文で送信するのではなく、暗号化されたハッシュを使用する。

  • EAP: Extensible Authentication Protocolは、さまざまな認証方式をサポートするためのフレームワークEAPを使用すると、ユーザ名/パスワードの組み合わせ、デジタル証明書、ハードウェアトークンなど、さまざまな認証方式を使用することができる。

  • EAP-TLS: EAP-TLSは、EAPの一種で、デジタル証明書を使用してクライアントとサーバ間の認証を行う。EAP-TLSは、ユーザ名/パスワードの組み合わせを使用するPAPやCHAPよりもセキュリティが強化されている。

RADIUSのパケット構造

  • Code (1バイト): パケットのタイプを指定する

  • Identifier (1バイト): 同一のRADIUSサーバが同時に処理する複数のリクエストを区別するためのID

  • Length (2バイト): 全体のパケット長を表す。パケットの最小長さは20バイトで、最大長さは4096バイト

  • Authenticator (16バイト): パケットの整合性を確認するための値。リクエストとレスポンスで異なる値を持つ

    • Request Authenticator
    • Response Authenticator
  • Attributes (可変長): TLV形式で、認証に必要な情報を含む

    • User-Name: ユーザ名
    • User-Password: パスワード
    • NAS Identifier: NASの識別子
    • Tunnnel-Password: トンネルパスワード
+----------------+
| Code (1 byte)  |
+----------------+
| Identifier     |
| (1 byte)       |
+----------------+
| Length         |
| (2 bytes)      |
+----------------+
| Authenticator  |
| (16 bytes)     |
+----------------+
| Attributes     |
| (Variable)     |
+----------------+

Access-Request例

Code: 1 (Access-Request)
Identifier: 10
Length: 44
Authenticator: 0x4f6a652fe681e2555b8e38a3c3a0e3c6
Attributes:
    - Type: 1 (User-Name)
      Length: 5
      Value: "user1"
    - Type: 2 (User-Password)
      Length: 16
      Value: 0x02030a3d4e5f (暗号化されたパスワード)
    - Type: 4 (NAS-IP-Address)
      Length: 6
      Value: "192.168.1.10"
    - Type: 5 (NAS-Port)
      Length: 6
      Value: 0

RADIUSプロトコルのシーケンス図

以下はRADIUSプロトコルのシーケンス図

RAIDUSプロトコルでは、Accountingはユーザーセッションの記録と追跡を行うために使用される。Accountingは、ユーザーがログオンするときに開始され、ログオフするときに終了する。Accountingは、ユーザーがログオフするまでの間、定期的に継続される。

https://plantuml-server.kkeisuke.dev/svg/XLBDIWCn4BxdAOQUBBJx03r8iuhWHMINFa38phQnsKpC90e-lRDRPLqHcqj8CjylsNCsAPV1goYxiowQa67rfDiL60Qzl6xq_UEXXHRJ6wPfe5PAm_OMQjY1jXQPjms-5kGCDmV65Co06tWspE-KkhMgluVlJcZFK6G4RC8EGtR6ip8-WoxvD9wjoOu2j6NYxOjN84iOX4BFUkCMHMw4KN8V5vGBFQqdGA2CG68OwXsqOrmUeLH48XmLUiRVaW_6UUp-bclm1MrM6Bf5yY-wEVsaz2DmWrOQ01QEKMBgNItOPmgE51XLLLMGtO0GfJ_apQKkJqS6wdkGvsiMAFxdWE8L0selCULpV080.svg

最大部分和問題

問題概要

n個の整数が与えられます。これらの整数から何個かを選んで総和をとったときの、総和の最大値を求めるプログラムを作成する。また、何も選ばない場合の総和は0とする

アプローチ

この問題は、ダイナミックプログラミングのアプローチを用いて解く。ダイナミックプログラミングは、複雑な問題をより簡単な部分問題に分割し、それらの結果を組み合わせて全体の問題を解く手法。

ここでは、dp[i] をi番目までの数から選んだ総和の最大値とする。このとき、次の状態 dp[i + 1] を次のように更新する:dp[i + 1] = max(dp[i], dp[i] + a[i])。これは、次の数 a[i] を選ぶか選ばないかのどちらが総和を最大にするかを比較する

コード

#include <algorithm>
#include <iostream>
using namespace std;

int n;
int a[10010];
int dp[10010];

int main() {
cin >> n;
for (int i = 0; i < n; ++i)
cin >> a[i];

dp[0] = 0;
for (int i = 0; i < n; ++i) {
dp[i + 1] = max(dp[i], dp[i] + a[i]);
}

cout << dp[n] << endl;
}

HTTPリクエストを送信してHTMLを取得する

Goのプログラム例 - HTTPリクエストを送信してHTMLを取得する

以下は、Go言語を使用して外部のURLからHTTPリクエストを送信し、そのレスポンスを取得してHTMLの内容を表示する。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    url := "http://google.co.jp"

    resp, err := http.Get(url)
    if err != nil {
        fmt.Println("Error making the HTTP request:", err)
        return
    }
    defer resp.Body.Close()
    // defer文を使って、resp.Bodyのクローズ処理を遅延実行します
    // これにより、関数の最後で確実にBodyを閉じることができる

    // レスポンスのボディを全て読み取ります
    byteArray, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response body:", err)
        return
    }

    fmt.Println(string(byteArray))
}