웹서비스와 utf-8

한국의 웹사이트들을 돌아다니다 보면 “파일이 보이지 않는 경우 ‘URL 을 항상 UTF-8 로 보냄’ 옵션을 꺼주시기 바랍니다.” 라는 메시지를 쉽게 볼 수 있다. 하지만 소위 웹프로그래머라는 사람들 중 저런 문제가 생기는 이유에 대해 관심 있는 사람들은 별로 없는 듯 싶다.

URIs

Internationalization of URIs is important because URIs may contain all kinds of information from all kinds of protocols or formats that use characters beyond ASCII. The URI syntax defined in RFC 2396 currently only allows as subset of ASCII, about 60 characters. It also defines a way to encode arbitrary bytes into URI characters: a % followed by two hexadecimal digits (%HH-escaping). However, for historical reasons, it does not define how arbitrary characters are encoded into bytes before using %HH-escaping.

Among various solutions discussed a few years ago, the use of UTF-8 as the preferred character encoding for URIs was judged best. This is in line with the IRI-to-URI conversion, which uses encoding as UTF-8 and then escaping with %hh:

Guidelines for new URL Schemes, RFC 2718, proposes to base URIs on UTF-8 unless there is some compelling reason for a particular scheme to do otherwise.
URI schemes or components already based on UTF-8:
URN syntax : RFC 2141 (syntactically, URNs look like a URI scheme, but semantically, they are not)
IMAP: RFC 2192 (the IMAP protocol uses a modified version of UTF-7, but its URIs use UTF-8)
FTP ( RFC 2640 uses UTF-8, but tolerates legacy encodings)
XPointer (W3C Working Draft)

From: http://www.w3.org/International/O-URL-and-ident

위에서 보다시피 RFC2718 에서는 URL 을 UTF-8 로 보내라고 제안하고 있으며, FTP 관련해서는 RFC2640 에서 path name 을 UTF-8 로 넘겨주라고 되어 있다. 그러므로 Internet Explore 에서 ‘URL 을 항상 UTF-8 로 보냄’ 을 해제시키는 것은 올바른 해결법이 아니라고 생각된다.

현재 까지의 대부분의 ftp client 에서 i18n 관련해서 별다른 고려를 하지 않고 있었기 때문에 path name 을 client 의 legacy charset 을 이용해서 넘겨주도록 구현되어 있다. 그렇기 때문에 (한글 기준으로) euc-kr 로 된 path name 이 사용되어 왔고 결국 server 측에도 euc-kr 로 저장되고 있는 실정이다.

그런 상황이다 보니 위의 권고안 대로 URL 을 UTF-8 로 넘겨주는 경우 실제 파일을 찾지 못하고 ‘404 Page Not Found’ 를 만나게 될 수 밖에 없는 것이다.

해결책은 간단하다고 생각한다. RFC2640 이 구현된 FTP server/client 를 사용하게 될 경우 자동으로 path name 에 UTF-8 을 사용하게 되므로 server 측에서 path name 에 별다른 조작을 가하지 않는 이상 filename 에 UTF-8 로 사용하게 될테고… 결국 UTF-8 로 된 URL 을 아무 문제없이 파일을 처리할 수 있게 된다.

얼른 이런 것들이 흥보가 되고 널리 쓰이게 되서 ‘URL 을 항상 UTF-8 로 보냄’ 을 체크해제 하라는 말을 안볼 수 있는 세상이 왔음 좋겠다 -_-;;

p.s) 현재 RFC2640 이 구현되어 있는 건 filezilla 밖에 모르겠네요. proftpd 의 경우 1.3.1rc 버젼부터 rfc2640 을 지원합니다.

이미지만으로 도배된 스팸

스팸들을 보다보면.. 내용은 하나도 없이 이미지 만으로 혹은 첨부파일 하나 딸랑 오는 메일들이 상당히 많다. 당연히 이미지 안에 내용을 전부 넣어버리기 때문에 필터링할만한 문자열이 아예 없다 -_-!! 그래서 생각인데 tag 를 깨끗이 비워버리고 trim 을 해보면 이런 메일들을 쉽게 거를 수 있지 않을까 싶다.

  1. title,style,script,object ~ /title,style,script,object 를 제거..
  2. 나머지 태그들을 깨끗이 제거!!
  3. trim

이 정도로만 해도 이미지로 도배된 스팸들은 다 거를 수 있지 않을까 싶은데… 뭐 역시나 귀차니즘이 문제 (어제 12시에 자러간 이후 지금까지 내 메일계정으로 온 스팸 중엔 스팸필터를 통과한 게 하나도 없다.. 친구껄로 온건 몇 개 있는거 같지만 -_-!!)

또한 본문을 seperator 기준으로 잘라서 토큰으로 만든 후… 영어로만 이루어진 토큰에 한해 spellcheck (aspell 같은걸 쓰면 되니까) 를 하고, spell 에 맞지 않는 것들의 수가 일정 % 이상이라면 스팸이라고 판단하는 방식도 유용하지 않을까 싶다.

스팸과의 전쟁 -_-!!

우선 게시판 스팸은 회원제로 바꿔버리면 반 이상은 해결할 수 있을거 같으니 제껴두고, procmail 룰 강화로 인해 필터링되지 않아야 할 메일이 필터링 되는 일이 있는지 체크할 겸 해서 로그를 남겨 지켜보는 중인데.. “광고” 라는 문구를 넣으면서도 필터링에서 피하기 위해 노력한 흔적들이 상당히 많이 보인다 -_-!!

  • 제목에 “(광고)” 란 단어를 넣긴 했지만.. base64 로 인코딩해서 보냄
  • 역시 제목에 “(광고)”란 단어를 넣긴 했지만.. quoted print 로 인코딩해서 보냄
  • &#unicode;&#unicode; 식의 방식을 사용.. “(광고)” 를 표현..

그 중 2번째와 세번째 같은 경우는 아예 인코딩된 글자 자체를 필터에 추가시키면 완벽하게 차단이 가능하지만, 문제는 첫번째 방식! base64 인코딩의 경우 7bit 단위로 잘라서.. 테이블을 이용 변환시켜버리기 때문에 “(광고)”라는 글자가 나오는 위치에 따라 결과가 많이 달라지기 때문에.. 필터링 못하는 경우도 생길 듯 하다.. base64 나 qprint 로 인코딩되서 오는 경우엔.. 오히려 어떤 charset 으로 표현된 글자인지를 알 수 있는 장점이 있으므로.. 저렇게 인코딩 해서 보내는게 나쁜건 아니지만.. 뭐 하튼 그렇다는 얘기…

최적의 솔루션이라면 디코딩을 한 후 유니코드로 변환해서 문자열 필터를 통과시키는 방법이겠지만.. 그럴려면 간단한 프로그램을 새로 짜야 하기 때문에, 귀찮은게지 -_-;; 또 제목이 전혀 인코딩되서 오지 않은 경우엔 어떤 언어인지 모르기 때문에 유니코드로 변환하는 도중에 예외 상황이 만들어지는 것도 문제고.. (사실 대강 끼워맞추기로 해결은 가능하지만)

[spoiler ‘simple”그동안의 성과 보기”숨기기’]

unfix skel # cat /var/log/procmail.log |grep ^[Adv|wc -l
429
unfix skel # cat /var/log/procmail.log |grep ^[Fake|wc -l
1561
unfix skel # cat /var/log/procmail.log |grep ^[Spam|wc -l
0
unfix skel # cat /var/log/procmail.log |grep ^[Viagra|wc -l
1
unfix skel # cat /var/log/procmail.log |grep ^[Virus|wc -l
2
unfix skel # cat /var/log/procmail.log |grep ^[Empty|wc -l
27
unfix skel # cat /var/log/procmail.log |grep ^[Bad|wc -l
127
unfix skel # cat /var/log/procmail.log |grep ^From|wc -l
493

[/spoiler]

지금까지의 작은 노력만으로도 결과는 만족스럽다는 사실 :)

유용한 procmail 용 rule!!

procmail 관련 해서 검색을 하던 중 아래와 같은 글을 발견했다. 내 스팸 함에 들어있는 메일들과 정상적인 메일들을 대강 훑어보았더니 저 룰만 가지고도 꽤 많은 스팸을 차단 할 수 있겠다는 생각이 들었다.

http://www.itinside.net/tips/045.html

multipart/alternative 방식은 text/plain 과 text/html 이 두 가지를 모두 가지고 있는 방식인데, 스팸 메일러에서 multipart/alternative 라고 선언을 해놓고 text/plain 혹은 text/html 둘 중 한 가지 만을 가지는 요상한 메일들을 보내는 경우가 많다는 점을 이용하는 것! 정상적인 mta 를 사용해서 보낼 경우 저런 잘못된 형식의 메일은 존재하지 않을 것이기 때문에 그냥 스팸이라고 간주해도 문제가 없을 것 같다.

(둘 중 하나만 집어 넣을거면 처음부터 text/plain, text/html 로 해서 보내면 된다. 첨부파일이 있다면 multipart/alternative 가 아닌 multipart/mixed 를 사용해야 하고…)

바로 적용시켜놔봤는데 결과가 어떨지는 자고 일어나 보면 알 수 있지 않을지 ;)

p.s) 원본 사이트가 없어져서 rule 을 quote 해놓습니다. 링크도 webarchive 쪽으로…

# This anti-fake method is to detect the format is incorrect.
:0 HB
* ^Content-Type: *multipart/alternative
* !^Content-Type: *text/plain
{
LOG = “[Fake] ”
:0
/dev/null
}

:0 EHB
* ^Content-Type: *multipart/alternative
* !^Content-Type: *text/html
{
LOG = “[Fake] ”
:0
/dev/null
}