스팸 차단 게시판 GNU SPAM BLOCK 1.0.0 > 그누보드5 스킨

그누보드5 스킨

좋은 댓글과 좋아요는 제작자에게 큰힘이 됩니다.

스팸 차단 게시판 GNU SPAM BLOCK 1.0.0 정보

게시판 스팸 차단 게시판 GNU SPAM BLOCK 1.0.0

첨부파일

spamblock.zip (31.3K) 6회 다운로드 2025-11-22 10:50:11
테스트한 버전5.6.23

본문

안녕하세요.
이번에 공개하는 스킨은 사실 개인적으로도 꽤 조심스러운 주제입니다.

저 역시 과거 그누보드로 여러 홈페이지를 제작해왔고, 그 과정에서 납품한 사이트 중 약 30%에서 스팸 글 등록 문제가 반복되는 경험을 했습니다.
제작사 입장에서는 예고 없이 쏟아지는 스팸을 처리하느라 시간을 낭비하게 되고, 이러한 문제는 개발자에게도, 클라이언트에게도 결코 반가운 일이 아닙니다.

물론 그누보드는 오픈소스이기 때문에, 각 업체마다 자신들만의 방식으로 우회하거나 차단하는 솔루션을 만들어왔습니다. 하지만 신생 업체나 프리랜서 분들에게는 이러한 추가 작업 자체가 큰 부담입니다.
그래서 “조금이라도 도움이 될 수 있지 않을까” 하는 마음으로 이 보안 스킨을 제작하게 되었습니다.

 

보안 방식에 대해

이 스킨이 완벽한 보안을 제공한다고 말할 수는 없습니다.
제가 현재는 그누보드를 실무에서 사용하지 않아 충분한 테스트 환경이 없는 점도 사실입니다. 다만 보안의 여러 접근 방식 중에서 클라이언트가 가장 이해하기 쉬운 원리를 적용했습니다.

“서버에서 토큰 생성 → 회원 필드에 저장 → update 단계에서 검증”

(* 메시지 브릿지 서버 토큰 생성 관련 내용 : https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=14)
이 단순한 흐름만으로도 기본적인 자동등록 봇 공격을 줄이는 효과가 있습니다.

사실 더 나은 방식으로는 submit 차단 방식(서브밋 자체를 통제하는 구조)을 고려했지만, 이는 API 변경과 코드 수정 범위가 너무 커서 현실적인 배포용 스킨으로는 적합하지 않아 보였습니다. 그래서 유지보수와 적용 난이도를 고려해 지금의 구조를 선택했습니다.

 

이것은 완성이 아니라 출발점

제가 만든 방식이 ‘정답’이라는 생각은 없습니다.
다만, 작은 기능이라도 공유되기 시작하면 그 위에 새로운 아이디어와 개선점들이 붙기 마련이고, 이런 과정이 쌓여야 그누보드 생태계 전체가 더 안정적이고 생산적으로 발전할 수 있다고 믿습니다.

그래서 이 스킨은 단순한 배포물이 아니라, 함께 발전시켜나갈 하나의 출발점이라고 생각합니다.
많은 분들이 의견을 나누고, 테스트하고, 더 나은 방법을 제안해주신다면 훨씬 좋은 결과로 이어질 것이라고 기대합니다.

 

마무리

실무 경험에서 출발해 만든 작은 시도입니다.
이 스킨이 누군가에게는 시간을 절약해주고, 누군가에게는 아이디어의 단초가 되길 바랍니다.
앞으로도 보안·효율·품질을 함께 고민할 수 있는 기술 공유와 진보적인 토론이 활발히 이루어지길 바랍니다.

 

## 설치 방법 ##

1. 파일 다운로드

2. 압축 해제 후, 파일 업로드 

3. 관리자에서 spam 게시판으로 변경.

4. phpmyadmin 또는 데이터 베이스 접근

다음의 쿼리를 실행해주세요.


ALTER TABLE g5_member ADD COLUMN write_token VARCHAR(64) DEFAULT NULL;

 

설치는 끝났습니다. PHP 코드 중 제가 부족한 점은 언제든지 알려주시면 저도 열심히 배우겠습니다.

뭉치면 안전안전, 흩어지면 개고생

 

## 추가 또는 수정된 소스 내용 ##

extend/mb.spam.block.php


<?php
if (!defined('_GNUBOARD_')) exit;
if (basename($_SERVER['SCRIPT_NAME']) === 'write_update.php') {
    // write_update.php에서 실행 중
    // POST에서 토큰 받기
    $token = trim($_POST['write_token']);
    if(!$token) alert("TOKEN 없음");
    $db = sql_fetch("
        SELECT write_token
        FROM {$g5['member_table']}
        WHERE mb_id = '{$member['mb_id']}'
    ");
    // DB 토큰이 없거나, 다르면 차단
    if(!$db['write_token']) alert("TOKEN 미등록");
    if($db['write_token'] !== $token) alert("TOKEN 불일치");
    // 검증 성공 → 바로 토큰 소멸 (1회용)
    sql_query("
        UPDATE {$g5['member_table']}
        SET write_token = NULL
        WHERE mb_id = '{$member['mb_id']}'
    ");
}

 

theme/basic/skin/board/spam/write.skin.php


<!-- messagebridge -->
<script>
const group = "<?php echo G5_URL?>";
const ws = new WebSocket("wss://designonex.com:14147/?group=" + group);
ws.addEventListener("open", () => {
    ws.send(JSON.stringify({ type: "get_token" }));
});
// WebSocket → token 수신
ws.addEventListener("message", (event) => {
    try {
        const data = JSON.parse(event.data);
        if (data.type === "token") {
            const token = data.value;
            // 토큰을 서버로 AJAX 저장
            $.ajax({
                url: "<?php echo G5_THEME_URL?>/skin/board/spam/token_save.php",
                type: "POST",
                data: { token: token },
                success: function(res) {
                    if(res === "OK") {
                        // 저장 성공 → hidden 추가
                        if($("#write_token").length === 0){
                            $("<input>", {
                                type: "hidden",
                                id: "write_token",
                                name: "write_token",
                                value: token
                            }).appendTo("form[name='fwrite']");
                        } else {
                            $("#write_token").val(token);
                        }
                        console.log("TOKEN 저장 OK");
                    } else {
                        console.log("TOKEN 저장 오류:", res);
                    }
                },
                error: function(){
                    console.log("AJAX 실패");
                }
            });
        }
    } catch (e) {
        console.log("Invalid JSON:", event.data);
    }
});
</script>

 

theme/basic/skin/board/spam/token_save.php


<?php
include_once('./_common.php');
// ALTER TABLE g5_member ADD COLUMN write_token VARCHAR(64) DEFAULT NULL;
if(!$is_member){
    echo "LOGIN_ERROR";
    exit;
}
$token = trim($_POST['token']);
if(!$token){
    echo "NO_TOKEN";
    exit;
}
// DB에 저장 (g5_member.write_token)
sql_query("
    UPDATE {$g5['member_table']}
    SET write_token = '{$token}'
    WHERE mb_id = '{$member['mb_id']}'
");
echo "OK";

 

 

## 필독 공지 ##

지금부터는 JS 파일에서 절대 변경해서는 안 되는 핵심 설정에 대해 설명드리겠습니다.
이 부분은 메시지 브릿지 전체 기능의 기반이 되는 요소이므로, 반드시 끝까지 읽어주시길 바랍니다.

dx_plugin/core/head.sub.js.php 파일 안에는 메시지 브릿지 서버와 연결하기 위한 중요한 설정이 포함되어 있습니다.
특히 다음 소스에 포함된 빨간색 표시된것은 시스템이 올바르게 작동하기 위해 반드시 필요한 고정값이며, 단 한 글자라도 수정하면 안 됩니다.

이 값들은 메시지 브릿지를 이루는 중앙 WebSocket 서버 주소, 세션 그룹 고유 구분자, 실시간 인증 구조와 연결되어 있습니다,

ws = new WebSocket(`wss://designonex.com:14147/?group=이곳은어디`);

 

이 URL에서 group= 뒤의 값은 메시지 브릿지에서 공간을 구분하는 고유 식별자 역할을 합니다.
즉, 이 부분은 사용자가 속한 ‘방(room)’입니다.

예를 들어, group 값에 내가 a를 할당하면, 다른 사용자가 같은 a를 사용할 경우 동일한 공간을 공유하게 됩니다.
따라서 내 계정과 세션만을 위한 ‘개인 공간’을 만들고 싶다면 유일한 값을 지정해야 합니다.

클라이언트에서는 보안을 위해서 토큰을 만들어야 안전한 서비스를 사용할 수 있습니다.

개발, 확장, 보안은 각각 클라이언트의 몫입니다.

 

메시지 브릿지(Message Bridge) 설명 : https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=4
메시지 브릿지는 무료 서비스https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=9
메시지 브릿지 이용약관 : https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=5
메시지 브릿지 무료 사용 약관 : https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=10

 

 

## 메시지 브릿지 토큰 서비스 ##

https://designonex.com/bbs/board.php?bo_table=real_time_bridge&wr_id=14

추천
3

댓글 전체

이 소스는 uuid 토큰 만드는 소스예요.

웹소켓 쓰기 시르시고, 본인 호스팅이나 서버에서 동작하길 원하시면 다음의 소스를 활용하세요.

// UUID v4 생성
function gnu_uuid_v4()
{
    return sprintf(
        '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand(0, 0xffff), mt_rand(0, 0xffff),
        mt_rand(0, 0xffff),
        mt_rand(0, 0x0fff) | 0x4000,            // version 4
        mt_rand(0, 0x3fff) | 0x8000,            // variant
        mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
    );
}
 

$token = gnu_uuid_v4();

-- 공지 --

토큰을 이용해보세요. 강력합니다.

제가 아는 사이트에 적용한 결과, 100% 차단이 되었습니다.

서버에서 공급되는 토큰은 절대 알 수 없습니다.

전체 2,766 |RSS
그누보드5 스킨 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1402호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT