(В этой статье описаны методы фильтрации спама, использованные в защищенном от спама веб-почтовом клиенте, который мы создали для тестирования Arc. Улучшенный алгоритм описан в статье «Улучшенная байесовская фильтрация».)
Я считаю, что спам можно остановить, и лучший способ сделать это — фильтры на основе содержимого. Ахиллесова пята спамеров — это их сообщение. Они могут обойти любую другую преграду, которую вы установите. По крайней мере, до сих пор им это удавалось. Но они обязаны доставить свое сообщение, каким бы оно ни было. Если мы сможем написать программу, распознающую их сообщения, обойти это они не смогут никак.
_ _ _
Получателю распознать спам легко. Если бы вы наняли человека, чтобы он читал вашу почту и выбрасывал спам, он справился бы без особого труда. Сколько нам нужно сделать, не прибегая к полноценному искусственному интеллекту, чтобы автоматизировать этот процесс?
Я думаю, что мы сможем решить эту проблему с помощью довольно простых алгоритмов. На самом деле я обнаружил, что современный спам можно фильтровать вполне приемлемо, используя всего лишь байесовскую комбинацию вероятностей спама для отдельных слов. С помощью слегка подправленного (как описано ниже) байесовского фильтра мы сейчас пропускаем менее 5 спам-писем на 1000, при нуле ложных срабатываний.
Статистический подход обычно не первое, что пробуют люди при написании спам-фильтров. Первый порыв большинства хакеров — попытаться написать программу, распознающую отдельные признаки спама. Вы смотрите на спам и думаете: какая наглость присылать мне письма, начинающиеся с «Дорогой друг» или с темой, написанной одними заглавными буквами и заканчивающейся восемью восклицательными знаками. Я могу отфильтровать это добро буквально одной строчкой кода.
И вы так и делаете, и поначалу это работает. Несколько простых правил отсекут значительную часть входящего спама. Простой поиск слова «click» выловит 79,7% писем в моем корпусе спама при всего 1,2% ложных срабатываний.
Я потратил около шести месяцев на написание программ, искавших отдельные признаки спама, прежде чем попробовал статистический подход. И я обнаружил, что распознать последние несколько процентов спама стало очень трудно, а по мере ужесточения фильтров я получал все больше ложных срабатываний.
Ложные срабатывания — это нормальные письма, которые ошибочно принимаются за спам. Для большинства пользователей пропустить важное письмо на порядок хуже, чем получить спам, поэтому фильтр, дающий ложные срабатывания, подобен лекарству от угрей, которое несет в себе риск смерти пациента.
Чем больше спама получает пользователь, тем менее вероятно, что он заметит одно невинное письмо среди завалов в папке со спамом. И как ни странно, чем лучше становятся ваши спам-фильтры, тем опаснее становятся ложные срабатывания, потому что, когда фильтры работают действительно хорошо, пользователи с большей вероятностью будут игнорировать все, что туда попадает.
Не знаю, почему я так долго избегал статистического подхода. Наверное, дело было в том, что я пристрастился выискивать признаки спама самостоятельно — словно играл со спамерами в какую-то соревновательную игру. (Люди не из мира технологий редко это понимают, но большинство хакеров очень азартны.) Когда я все же попробовал статистический анализ, то сразу понял, что он гораздо умнее меня. Он, конечно же, выяснил, что такие термины, как «virtumundo» и «teens», являются хорошими индикаторами спама. Но он также обнаружил, что «per», «FL» и «ff0000» тоже отличные признаки спама. На самом деле «ff0000» (html-код ярко-красного цвета) оказывается столь же надежным индикатором спама, как и любой порнографический термин.
_ _ _
Вот в общих чертах то, как я выполняю статистическую фильтрацию. Я начинаю с двух корпусов: один со спамом, второй с нормальной почтой. На данный момент в каждом из них около 4000 сообщений. Я сканирую весь текст каждого сообщения в обоих корпусах, включая заголовки, а также встроенный html и javascript. На данный момент я считаю буквенно-цифровые символы, дефисы, апострофы и знаки доллара частями токенов, а все остальное — разделителями токенов. (Здесь, вероятно, есть простор для улучшений.) Я игнорирую токены, состоящие только из цифр, а также игнорирую html-комментарии, даже не считая их разделителями токенов.
Я подсчитываю, сколько раз каждый токен (на данный момент без учета регистра) встречается в каждом корпусе. На этом этапе я получаю две большие хеш-таблицы, по одной на каждый корпус, сопоставляющие токены с количеством их вхождений.
Затем я создаю третью хеш-таблицу, на этот раз сопоставляющую каждый токен с вероятностью того, что содержащее его письмо является спамом, которую я вычисляю следующим образом [1]: (let ((g (* 2 (or (gethash word good) 0))) (b (or (gethash word bad) 0))) (unless (< (+ g b) 5) (max .01 (min .99 (float (/ (min 1 (/ b nbad)) (+ (min 1 (/ g ngood)) (min 1 (/ b nbad))))))))) где word — это токен, вероятность которого мы вычисляем, good и bad — хеш-таблицы, созданные на первом шаге, а ngood и nbad — количество не-спама и спам-сообщений соответственно.
Я привел это в виде кода, чтобы показать пару важных деталей. Я хочу немного сместить вероятности, чтобы избежать ложных срабатываний, и методом проб и ошибок я нашел хороший способ: удвоить все числа в good. Это помогает различать слова, которые изредка встречаются в нормальных письмах, и слова, которые там почти никогда не появляются. Я учитываю только те слова, которые в общей сложности встречаются более пяти раз (на самом деле из-за удвоения достаточно трех вхождений в обычной почте). И затем возникает вопрос, какую вероятность присваивать словам, которые встречаются в одном корпусе, но отсутствуют в другом. Опять же методом проб и ошибок я выбрал .01 и .99. Здесь еще возможна тонкая настройка, но по мере роста корпуса она все равно произойдет автоматически.
Особенно внимательные заметят, что хотя для подсчета вхождений я рассматриваю каждый корпус как единый длинный поток текста, в качестве делителя при расчете вероятностей спама я использую количество писем в каждом корпусе, а не их общую длину. Это добавляет еще одно небольшое смещение для защиты от ложных срабатываний.
Когда приходит новое письмо, оно разбивается на токены, и пятнадцать самых интересных из них (где интересность измеряется тем, насколько их спам-вероятность далека от нейтральной 0,5) используются для вычисления вероятности того, что письмо — спам. Если probs — это список из пятнадцати отдельных вероятностей, вы вычисляете объединенную вероятность так: (let ((prod (apply #'* probs))) (/ prod (+ prod (apply #'* (mapcar #'(lambda (x) (- 1 x)) probs))))) Один практический вопрос заключается в том, какую вероятность присвоить слову, которого вы никогда раньше не видели, то есть отсутствующему в хеш-таблице вероятностей слов. Опять же экспериментальным путем я выяснил, что хорошее значение — 0,4. Если вы никогда раньше не видели слова, оно, вероятно, вполне безобидно; спамерские слова, как правило, чересчур знакомы.
Примеры применения этого алгоритма к реальным письмам приведены в приложении в конце статьи.
Я считаю письмо спамом, если приведенный выше алгоритм дает вероятность того, что это спам, более 0,9. Но на практике не имело бы большого значения, где именно я установлю этот порог, поскольку мало какие вероятности оказываются в середине диапазона.
_ _ _
Одно огромное преимущество статистического подхода в том, что вам не приходится читать столько спама. За последние полгода я прочитал буквально тысячи спам-писем, и это действительно действует угнетающе. Норберт Винер говорил, что если соревнуешься с рабами, сам становишься рабом; в соревновании со спамерами есть нечто столь же унизительное. Чтобы выявлять отдельные признаки спама, вам приходится пытаться проникнуть в голову спамера, а я, честно говоря, хочу проводить в головах спамеров как можно меньше времени.
Но главное преимущество байесовского подхода, конечно, в том, что вы понимаете, что именно измеряете. Фильтры, распознающие отдельные признаки, такие как SpamAssassin, присваивают письму спам-«балл». Байесовский же подход вычисляет настоящую вероятность. Проблема с «баллом» в том, что никто не знает, что он означает. Пользователь не знает, что он значит, но что еще хуже — этого не знает и разработчик фильтра. Сколько баллов должно получить письмо за наличие слова «sex»? Вероятность, разумеется, может быть ошибочной, но в том, что она означает или как должны объединяться свидетельства для ее расчета, двусмысленности нет. Исходя из моего корпуса, «sex» указывает на 0,97 вероятности того, что содержащее его письмо — спам, тогда как «sexy» дает вероятность 0,99. А формула Байеса, столь же однозначная, гласит, что письмо, содержащее оба слова, при (маловероятном) отсутствии любых других свидетельств будет иметь 99,97% вероятности оказаться спамом.
Поскольку он измеряет вероятности, байесовский подход учитывает все свидетельства в письме — как плохие, так и хорошие. Слова, которые непропорционально редко встречаются в спаме (например, «though», «tonight» или «apparently»), способствуют снижению вероятности ровно так же, как плохие слова вроде «unsubscribe» и «opt-in» способствуют ее повышению. Так что обычное безобидное письмо, в котором случайно встретилось слово «sex», спамом помечено не будет.
В идеале, конечно, вероятности должны рассчитываться индивидуально для каждого пользователя. Я получаю много писем со словом «Lisp» и (пока что) ни одного спам-письма с ним. Так что подобное слово фактически служит чем-то вроде пароля для отправки мне почты. В моей более ранней программе фильтрации пользователь мог задать список таких слов, и письма, содержащие их, автоматически проходили через фильтры. В свой список я внес слова вроде «Lisp», а также свой почтовый индекс, чтобы квитанции об онлайн-заказах (звучащие в иных случаях довольно подозрительно) проходили без помех. Я думал, что поступил очень умно, но обнаружил, что байесовский фильтр сделал то же самое за меня, и к тому же нашел кучу слов, о которых я даже не подумал.
Когда в начале я сказал, что наши фильтры пропускают менее 5 спам-писем на 1000 при 0 ложных срабатываний, речь шла о фильтрации моей почты на основе корпуса моих писем. Но эти цифры не вводят в заблуждение, потому что именно такой подход я и предлагаю: фильтровать почту каждого пользователя на основе полученного им спама и нормальных писем. По сути, у каждого пользователя должно быть две кнопки удаления: обычное удаление и «удалить как спам». Все, что удалено как спам, отправляется в корпус спама, а все остальное — в корпус нормальной почты.
Для старта пользователям можно давать базовый фильтр, но в конечном итоге у каждого должны быть свои вероятности для каждого слова, основанные на фактически получаемой им почте. Это (а) делает фильтры более эффективными, (б) позволяет каждому пользователю самому определять, что для него спам, и (в) пожалуй, самое главное — мешает спамерам подгонять письма для прохождения фильтров. Если большая часть «интеллекта» фильтра находится в индивидуальных базах данных, то простая подгонка спама под базовые фильтры ничего не гарантирует в отношении того, насколько хорошо он пройдет сквозь разнообразные и гораздо лучше обученные фильтры отдельных пользователей.
Фильтрацию по содержимому часто комбинируют с белым списком — списком отправителей, чья почта принимается вообще без фильтрации. Один из простых способов составить такой список — сохранять адрес каждого, кому пользователь когда-либо отправлял письмо. Если в почтовой программе есть кнопка «удалить как спам», вы также можете добавлять адрес отправителя каждого письма, которое пользователь удалил как обычный мусор.
Я сторонник белых списков, но скорее как способа сэкономить вычислительные ресурсы, чем повысить качество фильтрации. Раньше я думал, что белые списки упростят фильтрацию, ведь фильтровать придется только письма от людей, о которых вы никогда не слышали, а человек, пишущий вам впервые, скован приличиями в том, что он может сказать. Кто-то из ваших знакомых может прислать вам письмо с разговорами о сексе, но тот, кто пишет впервые, вряд ли станет это делать. Проблема в том, что у людей может быть несколько адресов электронной почты, поэтому новый адрес отправителя не гарантирует, что человек пишет вам в первый раз. Для старого друга (особенно если он хакер) вполне обычно внезапно отправить вам письмо с нового адреса, так что нельзя рисковать ложными срабатываниями, фильтруя почту с неизвестных адресов с особой строгостью.
В определенном смысле, впрочем, мои фильтры сами по себе воплощают некий белый (и черный) список, поскольку они работают со всем сообщением целиком, включая заголовки. Таким образом, они в какой-то мере «знают» электронные адреса доверенных отправителей и даже маршруты, по которым почта доходит от них до меня. И то же самое они знают о спаме, включая имена серверов, версии почтовых клиентов и протоколы.
_ _ _
Если бы я считал, что смогу удерживать текущие показатели фильтрации, я бы счел проблему решенной. Но возможность отфильтровать большую часть сегодняшнего спама мало что значит, потому что спам эволюционирует. В самом деле, большинство методов борьбы со спамом до сих пор напоминали пестициды, которые лишь порождают новую, устойчивую породу насекомых.
В отношении байесовских фильтров я настроен более оптимистично, потому что они эволюционируют вместе со спамом. Так, когда спамеры начинают использовать «c0ck» вместо «cock», чтобы обойти примитивные фильтры по отдельным словам, байесовские фильтры автоматически это замечают. Более того, «c0ck» — гораздо более уличающая зацепка, чем «cock», и байесовские фильтры точно знают, насколько сильнее она обличает.
И все же любой, кто предлагает план фильтрации спама, должен быть готов ответить на вопрос: если бы спамеры в точности знали, что вы делаете, насколько успешно они могли бы вас обойти? Например, я думаю, что если фильтрация на основе контрольных сумм станет серьезным препятствием, спамеры просто перейдут на методику «mad-lib» (игры в пропуски) для генерации текстов сообщений.
Чтобы победить байесовские фильтры, спамерам будет недостаточно сделать свои письма уникальными или перестать использовать отдельные неприличные слова. Им придется сделать свои письма неотличимыми от вашей обычной почты. А это, как мне кажется, свяжет их по рукам и ногам. Спам — это в основном коммерческие предложения, и если только вся ваша обычная почта не состоит сплошь из рекламы, спам неизбежно будет иметь другой характер. И спамерам, конечно же, придется изменить (и постоянно менять) всю свою инфраструктуру, потому что иначе заголовки будут выглядеть для байесовских фильтров столь же подозрительно, как и раньше, что бы они ни делали с текстом сообщения. Я недостаточно хорошо знаком с используемой спамерами инфраструктурой, чтобы знать, насколько сложно сделать заголовки невинными, но предполагаю, что это даже сложнее, чем замаскировать текст письма.
Если предположить, что они смогут решить проблему заголовков, спам будущего, вероятно, будет выглядеть примерно так: Привет. Подумал, тебе стоит взглянуть на это: http://www.27meg.com/foo потому что это максимум рекламного текста, который фильтрация по содержимому позволит оставить спамеру. (На самом деле даже такое письмо протащить через фильтры будет трудно, ведь если все остальное в письме нейтрально, вероятность спама будет зависеть от url, и потребуется немало усилий, чтобы тот выглядел нейтрально.)
Спамеры бывают самыми разными: от компаний с так называемыми opt-in-рассылками, которые даже не пытаются скрыть свои данные, до дельцов, взламывающих почтовые серверы для рассылки спама с рекламой порносайтов. Если с помощью фильтрации мы сведем их возможности к сообщениям вроде приведенного выше, это практически лишит бизнеса спамеров из «легального» конца спектра; законы различных штатов обязывают их включать шаблонный текст о том, почему их спам — не спам, и как отменить «подписку», а такой текст легко распознать.
(Раньше я считал наивным верить, что ужесточение законов уменьшит количество спама. Теперь я думаю, что хотя более строгие законы, возможно, и не уменьшат количество спама, которое спамеры отправляют, они определенно могут помочь фильтрам снизить объем спама, который получатели реально видят.)
В любой части этого спектра ограничение спамеров в рекламных формулировках неизбежно приведет к их разорению. Слово бизнес здесь ключевое, о нем важно помнить. Спамеры — это бизнесмены. Они рассылают спам, потому что это работает. Это работает, потому что, хотя отклик чудовищно низок (в лучшем случае 15 на миллион против 3000 на миллион у рассылки бумажных каталогов), затраты для них практически нулевые. Затраты колоссальны для получателей — около 5 человеко-недель на каждый миллион получателей, тратящих по секунде на удаление спама, — но спамеру за это платить не приходится.
Тем не менее рассылка спама чего-то спамеру да стоит. [2] Так что чем ниже мы сможем опустить долю откликов — будь то фильтрацией или принуждением спамеров размывать свои рекламные тексты с помощью фильтров, — тем меньше компаний сочтут рассылку спама стоящим делом.
Причина, по которой спамеры используют именно такие продающие формулировки, заключается в стремлении повысить отклик. Возможно, это еще отвратительнее, чем влезать в голову спамера, но давайте бросим беглый взгляд на мысли того, кто откликается на спам. Этот человек либо поразительно легковерен, либо глубоко отрицает свои сексуальные интересы. В любом случае, каким бы омерзительным или идиотским спам ни казался нам, для них он привлекателен. Спамеры не писали бы всего этого, если бы это не звучало заманчиво. А фраза «подумал, тебе стоит взглянуть на это» просто не будет иметь у получателя спама и сотой доли того притяжения, какое имеют нынешние тексты спамеров. Результат: не имея возможности содержать завлекающие предложения, спам становится менее эффективным маркетинговым инструментом, и все меньше компаний захотят его использовать.
В этом и заключается конечная крупная победа. Я начал писать программу для фильтрации спама, потому что больше не хотел видеть эту дрянь. Но если мы научимся достаточно хорошо отфильтровывать спам, он перестанет работать, и спамеры просто перестанут его рассылать.
_ _ _
Из всех подходов к борьбе со спамом, от программных до законодательных, я считаю байесовскую фильтрацию самым эффективным. Но я также считаю, что чем больше разнообразных мер против спама мы предпринимаем, тем лучше, поскольку любая мера, связывающая спамеров, в конечном счете облегчает фильтрацию. И даже в области контентной фильтрации, я думаю, будет здорово, если параллельно будет использоваться множество различных программ. Чем больше разнообразных фильтров существует, тем труднее спамерам будет подгонять свои письма, чтобы проскользнуть сквозь них.
Приложение: примеры фильтрации
Вот пример спам-письма, пришедшего, пока я писал эту статью. Пятнадцать самых интересных слов в этом спаме: qvp0045 indira mx-05 intimail $7500 freeyankeedom cdo bluefoxmedia jpg unsecured platinum 3d0 qves 7c5 7c266675 Эти слова — смесь данных из заголовков и текста письма, что типично для спама. Также для спама типично то, что каждое из этих слов в моей базе данных имеет спам-вероятность 0,99. На самом деле слов с вероятностью 0,99 там больше пятнадцати, и это просто первые пятнадцать встретившихся.
К сожалению, из-за этого данное письмо оказывается скучным примером применения правила Байеса. Чтобы увидеть интересное разнообразие вероятностей, нам нужно взглянуть на этот, в сущности, довольно нетипичный спам.
Пятнадцать самых интересных слов в этом спаме вместе с их вероятностями: madam 0.99 promotion 0.99 republic 0.99 shortest 0.047225013 mandatory 0.047225013 standardization 0.07347802 sorry 0.08221981 supported 0.09019077 people's 0.09019077 enter 0.9075001 quality 0.8921298 organization 0.12454646 investment 0.8568143 very 0.14758544 valuable 0.82347786 На этот раз улики представляют собой смесь хороших и плохих. Такое слово, как «shortest», служит почти столь же сильным доказательством невиновности, сколь слова вроде «madam» или «promotion» — вины. Но все же доводы в пользу вины перевешивают. Если объединить эти числа по правилу Байеса, итоговая вероятность составит 0,9027.
«Madam» очевидно берется из спам-писем, начинающихся с «Dear Sir or Madam». Они не очень распространены, но слово «madam» никогда не встречается в моих обычных письмах, а все дело именно в соотношении.
«Republic» получает высокий балл, потому что часто мелькает в письмах «нигерийских мошенников», а также раз или два встречается в спаме с упоминанием Кореи и Южной Африки. Вы можете сказать, что помощь этого слова в распознавании спама — чистая случайность. Но изучая спам-вероятности, я обнаружил массу подобных случайностей, и у них есть поразительное свойство подталкивать результат в правильном направлении, а не в ошибочном. В данном случае появление слова «Republic» в нигерийских письмах и в этом спаме — не совсем совпадение. Существует целый класс сомнительных деловых предложений, связанных с развивающимися странами, а у тех, в свою очередь, чаще встречаются названия, явно подчеркивающие (потому что на деле это не так), что они республики.[3]
С другой стороны, «enter» — это чистый промах. Оно чаще всего встречается в инструкциях по отписке, но здесь используется в совершенно невинном контексте. К счастью, статистический подход достаточно устойчив и способен выдержать довольно много промахов, прежде чем результаты начнут искажаться.
Для сравнения, вот пример редкой птицы — спама, проскользнувшего через фильтры. Почему? Потому что по чистой случайности он оказался напичкан словами, которые встречаются в моей реальной переписке: perl 0.01 python 0.01 tcl 0.01 scripting 0.01 morris 0.01 graham 0.01491078 guarantee 0.9762507 cgi 0.9734398 paul 0.027040077 quite 0.030676773 pop3 0.042199217 various 0.06080265 prices 0.9359873 managed 0.06451222 difficult 0.071706355 Здесь есть пара хороших новостей. Во-первых, это письмо, скорее всего, не прошло бы через фильтры человека, который случайно не специализируется на языках программирования и у которого нет близкого друга по имени Morris. Для обычного пользователя все пять первых слов были бы нейтральными и не уменьшали бы спам-вероятность.
Во-вторых, я думаю, что фильтрация на основе пар слов (см. ниже) вполне могла бы его поймать: «cost effective», «setup fee», «money back» — весьма красноречивые улики. И конечно же, если бы они продолжили спамить меня (или сеть, частью которой я являюсь), само слово «Hostex» стало бы распознаваться как признак спама.
Наконец, вот нормальное письмо. Пятнадцать самых интересных слов в нем выглядят следующим образом: continuation 0.01 describe 0.01 continuations 0.01 example 0.033600237 programming 0.05214485 i'm 0.055427782 examples 0.07972858 color 0.9189189 localhost 0.09883721 hi 0.116539136 california 0.84421706 same 0.15981844 spot 0.1654587 us-ascii 0.16804294 what 0.19212411 Большинство слов здесь указывает на то, что письмо нормальное. Есть два слова с душком: «color» (спамеры обожают цветные шрифты) и «California» (которое встречается в отзывах, а также в выпадающих меню форм), но их недостаточно, чтобы перевесить очевидно невинные слова вроде «continuation» и «example».
Любопытно, что слово «describe» расценивается как столь безоговорочно невинное. Оно не встретилось ни в одном из моих 4000 спам-писем. Данные, как оказывается, полны таких сюрпризов. Одна из вещей, которые узнаешь при анализе текстов спама, — это то, насколько узким подмножеством языка оперируют спамеры. Именно этот факт вместе со столь же характерным словарем переписки каждого отдельного пользователя делает байесовскую фильтрацию столь многообещающей.
Приложение: Еще идеи
Одна идея, которую я еще не пробовал, заключается в том, чтобы фильтровать письма на основе пар или даже троек слов, а не отдельных слов. Это должно дать гораздо более точную оценку вероятности. Например, в моей текущей базе данных слово «offers» имеет вероятность 0,96. Если рассчитывать вероятности по парам слов, то у «special offers» и «valuable offers» окажется вероятность 0,99, а, скажем, у «approach offers» (как в «this approach offers») — вероятность 0,1 или меньше.
Причина, по которой я этого не сделал, в том, что фильтрация на основе отдельных слов уже работает очень хорошо. Но это означает, что есть возможность ужесточить фильтры, если спам станет труднее обнаруживать. (Любопытно, что фильтр на основе пар слов по сути представлял бы собой генератор текста на цепях Маркова, работающий в обратном направлении.)
Специфические признаки спама (например, отсутствие адреса получателя в поле to:), конечно, полезны для его распознавания. Их можно учесть в этом алгоритме, рассматривая как виртуальные слова. Вероятно, я сделаю это в будущих версиях, по крайней мере для горстки самых вопиющих признаков спама. Фильтры, распознающие отдельные паттерны, правы во многих деталях; чего им не хватает, так это общей системы для объединения доказательств.
Распознавать признаки не-спама может быть даже важнее, чем распознавать признаки спама. Ложные срабатывания вызывают такое беспокойство, что требуют чрезвычайных мер. В будущих версиях я, вероятно, добавлю второй уровень проверки, разработанный специально для предотвращения ложных срабатываний. Если письмо активирует этот второй уровень фильтров, оно будет принято, даже если его вероятность оказаться спамом выше пороговой.
Я не ожидаю, что этот второй уровень фильтрации будет байесовским. Он неизбежно окажется не просто ситуативным (ad hoc), но и основанным на догадках, поскольку число ложных срабатываний обычно будет недостаточно велико, чтобы выявить закономерности. (Впрочем, даже к лучшему, если резервная система не полагается на ту же технологию, что и основная.)
Еще одна вещь, которую я могу попробовать в будущем, — это уделять дополнительное внимание определенным частям письма. Например, около 95% текущего спама содержит URL сайта, который вас призывают посетить. (Остальные 5% предлагают позвонить по номеру телефона, ответить по электронной почте или на обычный почтовый адрес в США, либо в редких случаях купить определенные акции.) В таких случаях URL практически сам по себе достаточен для того, чтобы определить, является ли письмо спамом.
Доменные имена отличаются от остального текста в письме (если оно не на немецком языке) тем, что часто состоят из нескольких склеенных слов. Хотя в общем случае это вычислительно затратно, возможно, стоит попытаться разбивать их на части. Если фильтр никогда раньше не встречал токен «xxxporn», его индивидуальная вероятность спама составит 0,4, тогда как «xxx» и «porn» по отдельности имеют вероятности (в моем корпусе) 0,9889 и 0,99 соответственно, а их совокупная вероятность равна 0,9998.
Я ожидаю, что разбор доменных имен станет важнее по мере того, как спамеры будут вынуждены прекратить использование компрометирующих слов в тексте своих сообщений. (URL с IP-адресом, конечно же, является крайне компрометирующим признаком — за исключением почты редких сисадминов.)
Возможно, было бы неплохо создать совместными усилиями единый список URL-адресов, продвигаемых спамерами. Потребовалась бы метрика доверия того типа, который исследовал Раф Левиен (Raph Levien), чтобы предотвратить вредоносные или некомпетентные добавления, но если бы у нас было такое средство, оно стало бы мощным подспорьем для любого софта для фильтрации. Это также стало бы удобной основой для бойкотов.
Другой способ проверки сомнительных URL — отправлять краулер для анализа сайта до того, как пользователь откроет письмо с упоминанием этой ссылки. Можно использовать байесовский фильтр для оценки сайта точно так же, как и для письма, а все обнаруженное на сайте включать в расчет вероятности того, что письмо является спамом. URL, ведущий на редирект, конечно же, вызывал бы особое подозрение.
Один совместный проект, который мне кажется действительно хорошей идеей, — это накопление гигантского корпуса спама. Большой и чистый корпус — ключ к качественной работе байесовской фильтрации. Байесовские фильтры могли бы напрямую использовать этот корпус как входные данные. Но такой корпус был бы полезен и для других видов фильтров, поскольку его можно было бы использовать для их тестирования.
Создание подобного корпуса сопряжено с некоторыми техническими трудностями. Конечно, нам понадобятся метрики доверия для предотвращения злонамеренных или ошибочных добавлений. Также потребуются способы удаления личной информации (не только адресов to и cc, но и, например, параметров в ссылках для отписки, в которых часто закодирован адрес получателя) из писем в корпусе. Если кто-то захочет взяться за этот проект, это принесет миру огромную пользу.
Приложение: Определение спама
Я думаю, существует общее понимание того, что такое спам, но было бы полезно иметь четкое определение. Это необходимо, если мы хотим создать центральный корпус спама или хотя бы осмысленно сравнивать показатели эффективности фильтров спама.
Для начала: спам — это не просто «нежелательная коммерческая электронная почта» (unsolicited commercial email). Если бы кто-то по соседству услышал, что я ищу старый трехскоростной велосипед Raleigh в хорошем состоянии, и прислал мне письмо с предложением купить его, я был бы в восторге, хотя это письмо было бы и коммерческим, и незапрошенным. Определяющим признаком спама (по сути, его raison d'etre) является не то, что он незапрошен, а то, что он автоматизирован.
То, что спам обычно носит коммерческий характер, — тоже лишь случайность. Если бы кто-то начал массово рассылать письма в поддержку какого-либо политического движения, например, это было бы точно таким же спамом, как и рассылка с рекламой порносайта.
Я предлагаю определять спам как незапрошенную автоматизированную электронную почту. Таким образом, это определение включает в себя некоторые письма, которые не подпадают под многие юридические формулировки спама. Юридические определения, сформированные, по-видимому, под влиянием лоббистов, как правило, исключают рассылки от компаний, у которых есть «существующие отношения» с получателем. Но покупка товара у компании, например, вовсе не означает, что вы запросили регулярную рассылку от нее. Если я заказываю что-то в интернет-магазине, а они затем шлют мне потоки спама, это все равно спам.
Компании, рассылающие спам, часто предлагают возможность «отписаться» или просят перейти на их сайт и изменить «настройки учетной записи», если вы хотите перестать получать спам. Этого недостаточно, чтобы письмо перестало быть спамом. Отсутствие отказа (opt-out) — это не то же самое, что явное согласие (opt-in). Если только получатель явно не отметил галочкой понятный пункт (где по умолчанию было выбрано «нет») с просьбой получать рассылку, это спам.
В некоторых деловых отношениях вы действительно неявно запрашиваете определенные виды писем. Делая заказ онлайн, вы, как мне кажется, неявно запрашиваете квитанцию и уведомление об отправке заказа. Я не возражаю, когда Verisign присылает мне письмо с предупреждением об истечении срока регистрации доменного имени (по крайней мере, если они являются его фактическим регистратором). Но когда Verisign шлет мне письмо с предложением «БЕСПЛАТНОГО руководства по созданию сайта электронной коммерции» — это спам.
Примечания:
[1] Примеры в этой статье переведены на Common Lisp — верьте или нет — ради большей доступности. Описанное здесь приложение было написано нами для тестирования нового диалекта Lisp под названием Arc, который еще не выпущен.
[2] В настоящее время самый низкий тариф, по-видимому, составляет около 200 долларов за отправку миллиона спам-писем. Это очень дешево: 1/50 цента за письмо. Однако отсеивание хотя бы 95% спама увеличило бы затраты спамеров на охват определенной аудитории в 20 раз. Мало у кого найдется достаточная маржа, чтобы компенсировать такое.
[3] Как показывает опыт, чем больше определений стоит перед названием страны, тем более коррумпированы ее правители. Страна под названием «Социалистическая Народная Демократическая Республика X», вероятно, последнее место на земле, где вы захотели бы жить.
Спасибо Саре Харлин за вычитку черновиков; Дэниелу Гиффину (который также пишет продакшн-интерпретатор Arc) за несколько отличных идей по фильтрации и за создание нашей почтовой инфраструктуры; Роберту Моррису, Тревору Блэквеллу и Эранну Гату за многочисленные дискуссии о спаме; Рафу Левиену за советы по метрикам доверия; а также Чипу Колдвеллу и Сэму Стейнголду за консультации по статистике.
Дополнительная информация: