반응형

보안설계에서 중요한 키워드 WAF, Zero Trust Network


1. WAF (Web Application Firewall)

정의

웹 애플리케이션 계층(L7)의 보안 방화벽

HTTP 요청/응답을 검사해서 악의적인 공격을 차단하는 역할


WAF가 막아주는 공격 유형:

공격 설명

SQL Injection 쿼리에 악성 코드 삽입 시도
XSS (크로스 사이트 스크립팅) 자바스크립트 삽입 공격
CSRF 인증된 사용자의 권한 도용
경로 탐색(Path Traversal) 파일 시스템 침투 시도
봇 트래픽 차단 스크래퍼, 크롤러, 무차별 대입 공격 차단 등

WAF는 어디에 위치하냐면:

[클라이언트]
   ↓
[WAF] ← 모든 HTTP 요청 검사
   ↓
[웹 서버 / 프록시 서버]
   ↓
[WAS]


WAF 종류

구분 예시

하드웨어 F5 ASM, Imperva
소프트웨어 ModSecurity (Apache/Nginx), NAXSI
클라우드형 AWS WAF, Cloudflare WAF, Azure WAF

2. Zero Trust Network (제로 트러스트 네트워크)

정의

"절대 아무도 신뢰하지 마라.

네트워크 내부든 외부든 모든 요청을 검증하고 최소한의 권한만 허용하라."


핵심 개념:

개념 의미

No implicit trust 내부망이라고 무조건 믿지 않음
모든 요청 인증/인가 사용자, 장치, 앱 단위 인증 필수
최소 권한 원칙 필요한 자원에만 접근 가능
세션 기반 보안 로그인 이후에도 지속적 확인 (MFA, 토큰 검사 등)

Zero Trust 흐름 예시:

[사용자 또는 디바이스 요청]
      ↓
[인증 시스템 (IDP, MFA 등)]
      ↓
[Zero Trust 게이트웨이 (ZTNA Proxy)]
      ↓
[애플리케이션]


구성 요소 예시:

요소 예시

ID 관리 Okta, Azure AD
접근 제어 Zscaler, Cloudflare Zero Trust, Tailscale
정책 엔진 Google BeyondCorp, Istio (서비스메쉬)

WAF vs Zero Trust 비교

항목 WAF Zero Trust

방어 대상 웹 애플리케이션 네트워크 전체 (사용자/디바이스/앱 등)
작동 계층 L7 (HTTP) 전 계층 (ID, 네트워크, 앱, 세션 등)
보안 방식 패턴 매칭, 룰 기반 인증, 정책, 신뢰 검증
목적 공격 차단 (XSS, SQLi 등) 접근 제한 + 인증 기반 통제
설치 위치 웹 서버 앞단 네트워크 게이트웨이, 클라이언트 단 등

한 줄 정리

용어 요약

WAF 웹 공격 막는 L7 보안 필터
Zero Trust "내부망도 믿지 마" 철학으로 모든 요청을 지속적으로 검증
반응형

'공부 > CS' 카테고리의 다른 글

HLS 프로토콜  (1) 2025.06.02
API Gateway  (0) 2025.03.24
워터마크 기술 개념  (0) 2025.03.03
아키텍처 간략 정리  (0) 2025.01.05
언어별 연산 속도  (0) 2024.12.30
반응형

volatile은 자바에서 멀티스레딩 환경에서 자주 사용되는 키워드로, 변수에 대한 가시성(visibility)을 보장해 주는 기능


volatile이란?

volatile 키워드는 변수 선언 앞에 붙여서 사용되며, 해당 변수가 여러 스레드에서 동시에 접근될 수 있음을 나타냅니다.


private volatile boolean running = true;

필요한 상황

자바에서 멀티스레딩을 할 때, 각 스레드는 자신만의 캐시에 변수 값을 저장할 수 있음

이때, 한 스레드가 변경한 값이 다른 스레드에 보이도록 캐시 업데이트 진행

예시:

class Example implements Runnable {
    private boolean running = true;

    public void run() {
        while (running) {
            // do something
        }
    }

    public void stop() {
        running = false;
    }
}

이 코드는 stop() 메서드에서 runningfalse로 바꾸더라도, run() 내부의 스레드는 true만 계속 보고 멈추지 않음


private volatile boolean running = true;

volatile의 효과

  1. 가시성 보장 (Visibility)
    • 어떤 스레드가 값을 바꾸면, 다른 모든 스레드는 그 변경을 즉시 볼 수 있습니다.
  2. 원자성은 보장하지 않음 (No Atomicity)
    • volatile읽기/쓰기 자체는 원자적이지만, 복합 연산(++, += 등)은 원자적이지 않아요.
    • 예: count++volatile로도 안전하지 않습니다.

volatile vs synchronized

특징 volatile synchronized
가시성 O O
원자성 X O
성능 빠름 상대적으로 느림 (락 걸림)
용도 단순 플래그, 읽기/쓰기 변수 복잡한 상태 공유, 연산 등

🔸 사용 예시

public class FlagExample {
    private volatile boolean flag = false;

    public void setFlagTrue() {
        flag = true;
    }

    public void waitForFlag() {
        while (!flag) {
            // 대기 중
        }
        System.out.println("Flag detected!");
    }
}

요약

  • volatile은 멀티 스레드 환경에서 변수 값의 변경이 다른 스레드에 보이지 않는 문제(가시성 문제)를 해결하기 위해 사용된다.
  • 일반적으로 CPU는 변수 값을 자신의 캐시에 저장하고 사용하기 때문에, 한 스레드에서 변경한 값이 다른 스레드의 캐시에 반영되지 않아 변경이 전파되지 않는 문제가 발생할 수 있다.
  • volatile 키워드를 사용하면, 변수의 값을 항상 메인 메모리에서 읽고 쓰게 되어 최신 값이 모든 스레드에 보이도록 보장할 수 있다.

  • Thread A는 여전히 true인 줄 알고 계속 루프를 돔
  • Thread B는 메모리에서 false로 바꿨지만, A는 캐시된 값을 사용 중

  • Thread B가 false로 바꾸면
  • Thread A도 즉시 최신 값을 보고 루프 종료
반응형
반응형

https://spody.tistory.com/216

https://spody.tistory.com/217

두 글을 정리요약했습니다.

발생 현상

  • AUIGrid(자바스크립트 라이브러리)를 사용하는 엑셀 다운로드 시 깨진 파일을 다운받음
  • 그러나 백엔드 서버에서 해당 파일을 저장해둔 위치에 가서 파일을 열어보면 정상적으로 열리는 상태
  • 다운로드 받은 파일(깨진 파일)과 정상 파일을 메모장으로 열어서 데이터 비교했을 때 파일이 쓰이다 만 것처럼 데이터가 들어가 있음 (깨진 파일은 데이터가 중간에 끊김)

발생 원인

  • 파일이 중간에 깨진 이유는 디스크 쓰기 작업이 완료(flush)되기 전에 파일을 반환했기 때문에 발생
  • 백엔드 서버의 로직을 봤을 때 해당 코드는 동기적으로 처리되어야 정상인데 왜 문제가 발생했는가?
    • AIP 서버에서 파일 데이터를 수신하면, 해당 데이터는 먼저 메모리 내 커널 페이지 캐시에 저장
    • 이 시점에서 쉘 스크립트 또는 PHP는 파일 쓰기 작업이 완료된 것으로 간주하고, 바로 다음 단계로 넘어감
    • 하지만 flush가 디스크에 완전히 반영되기 전 프론트엔드에서 해당 파일을 다운로드 받아 문제가 발생
    • 즉, 쓰기 지연(write-back) 상태에서 read가 먼저 발생해 깨진 파일을 받게 됨

해결 방안

  • 3초 딜레이 적용
    • AUIGrid에서 사용하는 백엔드 호출 로직(DrmService.php)에 sleep(3)을 추가하여 디스크 flush가 완료되도록 유도
  • 쉘 스크립트 내에서 파일 디스크 flush 유도
    • 반환받은 파일 데이터를 .tmp 확장자로 저장한 후, mv file.xlsx.tmp file.xlsx 방식으로 최종 이름 변경
    • mv는 atomic rename 동작이기 때문에 flush 유도에 효과적
  • Python fsync() 시스템콜 직접 호출
    • python3 -c "f = open('${ORIGINAL_PATH}', 'rb+'); import os; os.fsync(f.fileno()); f.close()"
    • 명시적으로 flush 요청을 보냄 (단, NFS 환경에서는 보장되지 않을 수 있음)

고려 사항

  • 해당 문제는 운영 환경에서만 발생하며, 개발 환경에서는 재현되지 않음
  • 운영 서버에서 직접 코드를 수정하거나 임시 로직을 삽입해 테스트할 필요가 있음
  • 백엔드에서 생성하는 다른 엑셀 암호화 파일들도 동일한 문제의 가능성이 있음
    • 단, 해당 로직은 후처리 과정이 존재해 자연스러운 딜레이가 발생했기 때문에 flush가 완료되었음
  • Content-Length 기반 .done + mv 전략은, 상대 서버가 전송하는 파일이 반드시 바이너리 형식이며 Content-Length를 정확하게 명시한다는 전제를 필요로 한다. 하지만 상대 서버가 우리가 직접 구현한 것이 아니라면, 전송 형식이 base64, gzip, chunked encoding 등으로 바뀌거나 Content-Length가 부정확할 수 있기 때문에, 이 전략은 실질적으로 적용이 불가능하다고 판단하여 제외함.

NFS(Network File System)를 곁들인 저장소

쉘 스크립트나 Python을 통해 flush를 직접 유도했음에도 불구하고, 운영 환경에서는 여전히 깨진 파일이 다운로드되었음.

이를 확인한 결과, 해당 파일이 저장된 위치는 NFS 마운트 스토리지였다.

NFS 환경 특성

  • NFS export 옵션 중 sync, async가 있음
  • 옵션이 명시되지 않으면 기본값은 async → flush 지연

NFS export 옵션 설명

  • sync:
    • 클라이언트의 write() 요청마다 NFS 서버가 디스크에 즉시 flush한 후 OK 응답 반환
    • 안정성 높음, 성능 낮음
  • async (기본값):
    • write() → 클라이언트 커널 캐시에 저장 → 일정 시간 후 NFS 서버에 전송
    • 서버에서도 메모리에 저장 후 나중에 flush (2단계 지연)
    • fsync() 호출 → 클라이언트는 COMMIT 요청을 보내지만, 서버 flush 시점은 커널이 결정
    • 이로 인해 flush 전에 장애 발생 시 데이터 손실 가능성 있음

NFS 환경에서 flush 요약

  • 백엔드 서버는 NFS 마운트 스토리지에 파일을 저장하고 있음
  • NFS의 async 설정 때문에 flush 요청이 디스크에 즉시 반영되지 않음
  • flush()나 fsync(), mv 등을 해도 NFS 서버의 커널 스케줄러가 flush 시점을 결정하기 때문에 클라이언트 입장에서 flush가 즉시 완료되었는지는 보장되지 않음

최종 해결 방안

  • NFS export 옵션을 sync로 바꾸는 건 성능 리스크가 커서 적용 어려움
  • 엑셀 파일은 사용자가 다운로드 받기만 하면 되므로, 3초 대기 정도는 큰 무리가 없음
  • 따라서 엑셀 path를 반환하기 전 sleep 3을 넣는 것이 현재 환경에선 가장 현실적인 대응
반응형

'LTF(learn through failure)' 카테고리의 다른 글

파일 flush 문제 공유 (NFS)  (0) 2025.04.13
파일 flush 문제 공유  (0) 2025.04.05

+ Recent posts