はじめに
通常、ウェブサービスではDos攻撃対策にはCloudflareやAkamaiなどを使うと思います。それはわかるんですが、この前、数当てゲームをクライアント側に課すことでDos攻撃を緩和する手法があることを知りました。
いろいろ調べてくると研究が出てくると思います。このように。https://link.springer.com/chapter/10.1007/978-3-319-70278-0_11
考え方
「サーバー側の計算能力を使うんだから、クライアント側の計算能力も使ってね」だと思います。
前に話題になった、Coinhiveなんかも「こっちのリソース使ってるなら、マイニング(計算)してこっちにも利益ちょうだいね」という考えなのだと思います。
現状のウェブは広告で成り立っている側面が強いと思いますが、計算が、ウェブ広告は通信量と**ブレインハック(無意識領域に訴えかけることでの洗脳など)**になるのだと思います。
どちらが好きかと聞かれると、難しいところです。ただ、前者(計算)の方が単純な気がします。後者は恐怖を感じる。
実際のコード
ということで、とりあえず数当てゲームをJavascriptで書いてみました。同期処理です。
sha3を使用します。sha3はライブラリを使いました。https://github.com/emn178/js-sha3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="sha3.min.js"></script>
<script src="protect.js"></script>
<title>Document</title>
</head>
<body>
<h1>Nyanko Challenge</h1>
<button id="btn">クリック</button>
<script type="text/javascript" defer="defer">
document.getElementById("btn").onclick = function() {
// 以下はふつうサーバー側で行う。
let passphrase = "Madoka";
let difficulty = 10 ** 6;
let random_string = sha3_512(passphrase + "_" + Math.round((new Date()).getTime() / 1000)); // 予測不可能な文字列であればOK
let nonce = Math.floor(Math.random() * difficulty);
console.log(nonce);
let target = sha3_512(random_string + nonce);
// 以下はクライアントがわ。
let solved = solve(random_string, target, difficulty);
}
</script>
</body>
</html>
function solve(rnd_str, target, difficulty) {
console.log('Hello World.')
n = 0
while (true) {
let susp_str = sha3_512(rnd_str + n);
if (susp_str == target) {
console.log('Match!' + n);
return true
}else{
// console.log(n);
if (n < difficulty) {
n ++
}else{
return false
}
}
}
}
ただ、クライアントがいい感じの実行時間、例えば5分や10分などで解き終えることが出来るような計算量を課すべきであることに注意してください。
リアルタイム処理が要求され、かつその処理が高負荷であるアプリケーションには向かないと思います。リアルタイム処理は不要だが、一つの処理に対する負荷が高いアプリケーション向けであると思います。
おわりに
前は個人データの所有権について書きましたが、今回はちょっと違った(レベルが低い)タイプの記事を書いてみました。
整理してて「なんやこれ」ってファイルを見つけたら、またこんな感じで適当にアップロードしていこうと思います。