본문
제가 관리하는 서버에 계속적으로 불법적인 접근과 게시판에 스펨남기는 문제로 고민하다가
해당 글에만 집중포화를 남기는점에 착안하여 해당글의 인덱스만 바꿔주는 걸로 문제는
해결했는데 jsboard를 붙인 곳에서는 이곳저곳 수시로 접근을해서 글을 남기는 문제가
남아있어서 아예 게시판을 막아버렸습니다.
이후 아파치의 error_log에 남는 IP를보고 도대체 어느나라에서 이렇게 들어오나하고
(대부분 영문이어서 미쿡쪽이 의심되었지만...) 궁금하던차에
http://swbae.egloos.com/1740580
이런글을 보게 되었습니다. 하지만 Perl이니 Python이니하는 것은 하나도 모르겠고
막상 소스를 받아서 실행해봤지만 무언지를 또 설치해야한다는데 무엇을 설치해야하는지
종잡을 수도 없고하던차에
http://www.maxmind.com/download/geoip/api/php/
GeoIP를 판매하는 사이트에서 예제파일을 보게 되어서 몇가지 수정을 거쳐서 PHP를 이용
WEB에서 지도를 표시할 수 있는 소스를 간단하게 만들어봤습니다.
일단 제가 관리하는 서버는 Gentoo를 이용해서 구축했습니다.
PHP에는 gd가 기본적으로 사용되도록 해놓았습니다.
PHP5를 사용하는데 PECL이 기본적으로 사용된다고 하네요. 그래서 PECL을 이용해서
geoip를 설치했습니다.
이것을 사용하기 위해서는 php.ini에 extension를 설정해 주어야합니다.
WEB이나 Console에서 사용하기 위해서 /etc/php/apache2-php5/php.ini와
/etc/php/cli-php5/php.ini 두곳모두 다음과 같은 코드를 넣어주었습니다.
위와 같이 'extension=geoip.so'를 추가해주면 됩니다.(앞에있는 651은 줄번호)
물론 WEB에서 사용하려면 아파치를 다시 실행시켜주어야합니다.
혹시 필요할지 몰라서 geoip 라이브러리도 설치했습니다.(GeoIP.dat가 필요할지도...)
# emerge dev-libs/geoip
phpinfo ()로 gd항목 다음에 geoip가 포함되는 것을 확인할 수 있습니다.
이렇게하면 기본적으로 사용할 수 있는 환경은 갖춰진 것입니다.
데이터들은 maxmind.com의 GeoIP 페이지에서 Free로 되어있는 자료들을 사용하시면
됩니다.
단지 나라만 필요하면 GeoIP.dat만으로도 충분하지만 제가 하려고 하는 작업은
지도에 표시하기 위함이니 위도와 경도가 나오는 GeoLiteCity.dat가 필요했습니다.
그래서 http://www.maxmind.com/app/geolitecity 이곳에서 해당 데이터를 받았습니다.
그리고 위 API사이트의 sample_city.php를 이용하여 다음과 같은 소스를 만들었습니다.
//
// 참고로 사용한 지구 이미지 크기는 2048x1024 입니다.
// http://xplanet.sourceforge.net/ 사이트에서 2000x1000크기의 이미지를 2048x1024로
// 변환한 이미지를 이용했습니다.
// 다른 사이즈의 이미지를 사용할 경우에는 아래 나와있는 계산식을 이용해서 변수와
// 계산식의 숫자를 조작하시면 됩니다.
// 폰트는 Alee님이 배포하신 Eunjin.ttf를 사용했습니다.
// 아래소스와 같은 디렉토리에 복사해주시면 됩니다.
//
<?php
// Console에서 사용하려면 아래 주석을 풀고 첫번째 칸으로 옮기면 됩니다.
//#!/usr/bin/php -q
// 기본적인 함수와 변수 포함. 이건 maxmind.com자료를 그대로...
include("geoipcity.inc");
include("geoipregionvars.php");
// $ip변수가 없으면 접속한 IP를 이용
if (!$ip)
$ip = $_SERVER ['REMOTE_ADDR'];
// 여기서 중요한건 경로는 절대경로를... 보안에 문제가 있을까요????
$gi = geoip_open("/usr/share/GeoIP/GeoIPCity.dat",GEOIP_STANDARD);
$record = geoip_record_by_addr($gi,$ip);
geoip_close($gi);
// 여기까지가 sample_city.php에 포함되어있는 내용입니다.
// $record에는 필요한정보가 들어가 있습니다.
// 자세한건 sample_city.php를 참조하세요.
// 시스템 locale때문에 지정했습니다.
setlocale (LC_ALL, "ko_KR.eucKR");
// 경도 : 그리니치(0도)를 기준으로 지구를 360도로 나누는 값
// 따라서 1도크기를 이미지에서 표시하려면 2048:360=x:1로해서
// 5.688888888 이라는 숫자를 얻을 수 있습니다.
$longitude = 5.6888888;
// 위도 : 적도를 중심으로 북/남으로 표시됩니다.(남쪽은 -로 표시됩니다.)
// 북쪽 90도 남쪽 90도로 총 180도가 됩니다.
// 따라서 1도 크기를 이미지에서 표시하려면 1024:180=y:1로해서
// 역시 5.68888888 이라는 숫자를 얻을 수 있습니다.
$latitude = 5.6888888;
$radius_x = 12; // IP를 표시하는 작은원의 세로지름
$radius_y = 9; // IP를 표시하는 작은원의 가로지름
$max_width = 1024; // 화면에 표시할 이미지 가로크기
$max_height = 768; // 화면에 표시할 이미지 세로크기
$image_name = "Day.jpg"; // 지도 이미지이름
$fontname = "Eunjin.ttf"; // 화면표시 폰트이름
// 기본 이미지를 만듭니다.
$base = @ImageCreateTrueColor ($max_width, $max_height)
or die ("Cannot Initialize new GD image stream");
// 기본색지정
$bg = ImageColorAllocate ($base, 200, 200, 200);
$black = ImageColorAllocate ($base, 0, 0, 0);
$white = ImageColorAllocate ($base, 255, 255, 255);
$red = ImageColorAllocate ($base, 255, 0, 0);
$green = ImageColorAllocate ($base, 0, 255, 0);
$blue = ImageColorAllocate ($base, 0, 0, 255);
// 배경 채우기
ImageFill ($base, 0, 0, $bg);
// 지도이미지 읽어들이기
$back = @ImageCreateFromJpeg ($image_name)
or die ("Cannot Initialize read JPEG image stream");
// IP의 경도와 위도로 지도에 위치 표시하기
// $record에는 경도와 위도의 값이 있습니다. 그값을 이용해서 지도에 원하는
// 위치를 표시합니다.
// 제가 참고한 지도는 그리니치시가 경도로 지도의 정 가운데에 있어서 그것을
// 계산하기위해서 1024를 더하고 나온 값을 1024로 나눈 나머지 값을 더해주는
// 형식을 사용했습니다.
$position_x = 1024 + ($longitude * $record->longitude) % 1024;
// 위도는 적도가 이미지의 중앙(512)에 위치하기때문에 그것을 기준으로 +-를
// 그대로 적용했습니다.
$position_y = 512 - ($latitude * $record->latitude);
// 빨간 원 그리기
ImageFilledEllipse ($back, $position_x, $position_y, $radius_x, $radius_y, $red);
// 지도 이미지를 바탕 이미지에 맞춰서 사이즈를 줄여 복사하는 방법입니다.
// $back다음에 3, 3 그리고 $max_width와 $max_height에서 6을 제외한것은 테두리를
// 만들기 위한 작업입니다. :-)
ImageCopyResized ($base, $back, 3, 3, 0, 0, $max_width - 6, $max_height - 6, ImageSx ($back), ImageSy ($back));
// 다사용한 지도이미지는 메모리에서 해제해줍니다.
ImageDestroy ($back);
// 화면에 정보를 글씨로 써주기 위한 작업입니다.
$str[0] = "Country : " . $record->country_code . " " . $record->country_code3 . " " . $record->country_name;
$str[1] = "Region : " . $record->region . " " . $GEOIP_REGION_NAME[$record->country_code][$record->region];
$str[2] = "City : " . $record->city;
$str[3] = "Postal : " . $record->postal_code;
$str[4] = "Latitude : " . $record->latitude;
$str[5] = "Longitude : " . $record->longitude;
$str[6] = "DMA : " . $record->dma_code;
$str[7] = "Area : " . $record->area_code;
// 대충 태평양 아래 텅빈공간에 정보를 표시해줍니다.
for ($i = 0; $i < 8; $i++)
ImageTTFText ($base, 10, 0, 20, 500 + $i * 18, $green, $fontname, $str [$i]);
// 이미지를 출력한다는 것을 알려줍니다.
// 주의할 것은 header를 사용할 때는 위 아래에 아무런 출력문도 있어서는 안됩니다. :-)
header ("Content-type: image/png");
// 이미지 출력. redirect를 이용하면 console에서도 이미지로 받을 수 있을겁니다.
ImagePng ($base);
// 다 사용한 배경 이미지는 메모리에서 해제...
ImageDestroy ($base);
?>
제가 Perl이나 Python만 알았어도 이런 삽질은 하지 않았을텐데 그걸 몰라서 이런 삽질을 하고있네요...
참고로 위 이미지 출력부분은 이전에 제가 심심풀이로 만들었던 달력에 사용했던 소스를 조금 수정했습니다.
만일 정리가 되면 그 소스도 올려보도록하죠. :-)
관련링크
- https://kldp.org/node/99601 591회 연결
댓글목록
등록된 댓글이 없습니다.