문자 발송 공격
한 회사 가 문자 인증 코드 를 사용 해 사용자 의 진실성 을 검증 한 이후 문자 메 시 지 는 회사 업무 의 표지 가 되 었 다.현재 거의 모든 회사 의 서비스 에는 문자 발송 이라는 기능 이 포함 되 어 있다.사용자 가 문 자 를 요청 할 때 보통 등록 되 지 않 았 기 때문에 이 인 터 페 이 스 는 익명 인터페이스 (로그 인 필요 없 음) 입 니 다.
그 러 자 나 쁜 놈 들 이 소란 을 피 우기 시작 했다.그들 은 소프트웨어 팩 을 통 해 사용자 의 요청 메 시 지 를 받 은 다음 에 사용자 가 서버 에 미 친 듯 이 이 요청 을 보 내 는 것 을 모 의 했다. 회사 의 문자 자원 을 소모 하고 무고 한 핸드폰 사용 자 를 괴 롭 히 며 심지어 문자 채널 이 막 혀 정상 적 인 메 시 지 를 보 내지 못 했다.어쩌면 괴롭힘 을 당 한 사람들의 고소 에 회사 의 문자 통 로 를 차단 하거나 각 휴대 전화 업 체 에 의 해 스 팸 메시지 로 인식 되 어 마 케 팅 효 과 를 잃 거나 정상 적 인 업무 에 영향 을 미 칠 수도 있다.
오늘 나 는 이런 말썽꾸러기 를 만 났 다.그의 손 에는 약 수천 대의 육계 가 있다.그래서 우 리 는 즉시 이 일 을 처리 하기 시작 했다.
해결 책
우 리 는 두 가지 전략 을 생각 해 냈 다.
우리 가 채택 한 전략 은 두 번 째 이다.
처음에 우 리 는 첫 번 째 IP 를 사용 하여 이 IP 를 iptables 에 직접 넣 었 습 니 다. 커 널 차원 에서 이 IP 를 막 았 습 니 다. 다만 우 리 는 봉인 을 해제 하 는 것 이 비교적 번 거 롭 고 우리 의 소프트웨어 와 통합 할 수 없다 고 생각 했 습 니 다. 특히 논리 적 통합 (인 터 페 이 스 를 구별 하여 1 분 에 1 번, 3 번 이상 허용 해 야 IP) 을 실현 하기 어렵 고 nginx + redis 방안 을 사 용 했 습 니 다.루 아 프로그램 은 내 가 원 하 는 논리 로 쓸 수 있 으 니까.
이루어지다
만약 우리 가 문 자 를 보 낸 인터페이스 가
/sendSms
ngix. conf 파일 server
세그먼트 에 정규 표현 식 location
과 일치 하도록 새 ~* sendSms
블록 이 라면 코드 를 쓰기 시작 합 니 다. location ~* sendSms {
default_type 'application/json; charset=UTF-8';
lua_need_request_body on;
access_by_lua ' -- lua , , ';
proxy_pass http://app_backend;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass_header Origin;
}
아래 lua 코드 는 위의 작은 따옴표 로 복사 하 십시오.
-- ngx.exit(ngx.OK)
local cjson = require "cjson"
local ip = ngx.var.remote_addr
if ngx.var.http_user_agent ~= nil or ngx.var.http_user_agent == "" then
local agent = string.lower(ngx.var.http_user_agent)
-- ngx.say("user agent:", ngx.var.http_user_agent)
-- ngx.exit(200)
local sIdx = string.find(agent, "httpclient") or string.find(agent, "java")
-- ngx.say("sIdx:", sIdx)
if (sIdx ~= nil) then
ngx.status = ngx.HTTP_FORBIDDEN
local msg = " , , , "
ngx.say(cjson.encode({code=16, msg=msg, R=cjson.null}))
ngx.exit(ngx.status)
return
end
end
local redis = require "resty.redis"
local red = redis.new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say("failed to connect: ", err)
return
end
local forbidden, err1 = red:sismember("fbdIP", ip)
-- ngx.say("forbidden:", forbidden)
if forbidden == 1 then
ngx.status = ngx.HTTP_FORBIDDEN
local msg = " , , , "
ngx.say(cjson.encode({code=16, msg=msg, R=cjson.null}))
ngx.exit(ngx.status)
return
end
local key = "ip::" .. ip
-- ngx.say("key:", key)
local ttl, err1 = red:ttl(key)
if ttl == -1 then
red:del(key)
end
local res, err = red:get(key)
red:incr(key)
if (not res) or (res == ngx.null) then
--[[ local msg = "failed to get cache" ngx.say(cjson.encode({code=16, msg=msg, R=cjson.null})) --]]
red:expire(key, 55) -- 55 IP 30
ngx.exit(ngx.OK)
elseif tonumber(res) < 1 then
ngx.exit(ngx.OK)
elseif tonumber(res) >= 1 then
ngx.status = 200
-- ngx.say("redis result is string 1")
-- local msg = " , "
local msg = " , "
ngx.say(cjson.encode({code=16, msg=msg, R=cjson.null}))
if tonumber(res) > 10 then
red:sadd("fbdIP", ip)
end
ngx.exit(ngx.status)
return
end
해명 하 다.
get()
뿐만 아니 라 ttl()
도 사 용 했 습 니 다. redis 의 만 료 회수 전략 은 LRU 와 비슷 한 알고리즘 을 사용 하여 일정 확률 로 삭제 되 지 않 기 때문에 ttl 을 사용 하여 검 사 했 습 니 다.전제 조건
여러분 이 이 글 을 읽 을 때, 나 는 이 방안 이 적용 되 는 전 제 를 말씀 드 리 겠 습 니 다.만약 이런 전제 가 없다 면 이 방안 은 너 에 게 사용 할 수 없다. 물론 생각 을 해결 하 는 데 도움 이 될 수 있 을 것 이다. 만약 에 네가 손 을 잘 쓰 면 곧 자신의 해결 방법 을 잘 할 수 있 을 것 이다.우리 의 시스템 은 다음 과 같은 몇 가지 조건 을 만족시킨다.
건의 하 다.
이전에 redis 는 루트 권한 을 얻 을 수 있 는 구멍 이 있 었 기 때문에:
redis 의 key 는 절대 오염 되 어 서 는 안 됩 니 다. 그렇지 않 으 면 정상 적 인 사용자 의 IP 가 잘못 손상 되 어 금 지 됩 니 다.
공구.
이 문 제 를 해결 할 때, 우 리 는 또한 많은 뇌 세 포 를 폐 기 했 습 니 다. 당신 의 뇌 세 포 를 절약 하기 위해 서, 나 는 무료 로 당신 에 게 보 여 드 리 겠 습 니 다.
나 쁜 놈 이 내 서버 를 공격 하고 있다 는 걸 어떻게 알았지?
나의 방법 은 로그 에 있 는 모든
/sendSms
인터페이스의 호출 IP 를 통계 함으로써 호출 횟수 가 비교적 많은 것 을 찾 는 것 이다. 예 를 들 어 10 번 이상 인 것 이다.이 명령 을 사용 하면 됩 니 다.grep "POST /sendSms" logs/ikuaiyue.log | awk '{print $6}' | sed s/IP:// | sort | uniq -c | awk '{print $1 "\t" $2}' | sort -n
그리고 이런 결 과 를 볼 수 있다.
1 115.205.13.179
2 117.136.40.20
2 117.136.94.44
2 117.59.39.22
122 223.104.10.28
첫 번 째 열 은 이 IP 의 호출 횟수 입 니 다. 두 번 째 열 은 알 고 있 습 니 다.자, 이제 고 치 는 법 알 겠 지?
참고 로 우리 의 일 지 는 이 모양 입 니 다.
[2016-05-30 01:25:20.451] [INFO] normal - IP:117.174.26.32 POST /sendSms
[2016-05-30 01:26:17.918] [INFO] normal - IP:117.174.26.32 POST /sendSms
...
위의 명령 을 조금 설명 하 세 요:
grep "POST /sendSms" logs/ikuaiyue.log
| awk '{print $6}' # 6 ( IP:117.174.26.32)
| sed s/IP:// # "IP:"
| sort #
| uniq -c # , ,
# ,IP .
# :
| awk '{print $1 "\t" $2}' # , , tab
| sort -n # 。-n ,
당신 이 나의 방법 에 따라 nginx 를 설정 한 후에 효과 가 있 는 지 없 는 지 어떻게 압 니까?
방금 그 명령 을 고치 고 마지막 3000 줄 만 출력 합 니 다.
tail -n3000 logs/ikuaiyue.log | grep "POST /sendSms" | awk '{print $6}' | sed s/IP:// | sort | uniq -c | awk '{print $1 "\t" $2}' | sort -n
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.