Skip to content

Commit

Permalink
Merge pull request jason5ng32#225 from jason5ng32/dev
Browse files Browse the repository at this point in the history
Add MAC lookup
  • Loading branch information
jason5ng32 authored Jul 11, 2024
2 parents 1df0057 + 4effe3f commit 94f2e0a
Show file tree
Hide file tree
Showing 13 changed files with 461 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ CLOUDFLARE_API=""
SECURITY_BLACKLIST_LOG_FILE_PATH=""
SECURITY_RATE_LIMIT=""
SECURITY_DELAY_AFTER=""
IPAPIIS_API_KEY=""
IPAPIIS_API_KEY=""
MAC_LOOKUP_API_KEY=""
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Notes: You can use my demo for free, and you can also deploy it yourself.
* 🔦 **DNS Resolver**: Performs DNS resolution of a domain name from multiple sources and obtains real-time resolution results that can be used for contamination determination.
* 🚧 **Censorship Check**: Check if a website is blocked in some countries.
* 📓 **Whois Search**: Perform whois information search for domain names or IP addresses
* 📀 **MAC Lookup**: Query information of a physical address
* 🌗 **Dark Mode**: Automatically toggles between dark and daylight modes based on system settings, with an option for manual switching.
* 📱 **Minimalist Mode**: A mobile-optimized mode that shortens page length for quick access to essential information..
* 🔍 **Search IP Information**: Provides a tool for querying information about any IP address.
Expand Down Expand Up @@ -101,6 +102,7 @@ You can use the program without adding any environment variables, but if you wan
| `IPAPIIS_API_KEY` | No | `""` | API Key for IPAPI.is, used to obtain IP geolocation information through IPAPI.is |
| `KEYCDN_USER_AGENT` | No | `""` | The domain name when using KeyCDN, must contain https prefix. Used to obtain IP address information through KeyCDN |
| `CLOUDFLARE_API` | No | `""` | API Key for Cloudflare, used to obtain AS system information through Cloudflare |
| `MAC_LOOKUP_API_KEY` | No | `""` | API Key for MAC Lookup, used to obtain MAC address information |

### Using Environment Variables in a Node Environment

Expand Down
2 changes: 2 additions & 0 deletions README_FR.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Notes: Vous pouvez utiliser ma démo gratuitement et vous pouvez également la d
* 🔦 **Résolveur DNS** : effectue la résolution DNS d'un nom de domaine à partir de plusieurs sources, obtient les résultats de la résolution en temps réel et peut être utilisé pour la détermination de la contamination.
* 🚧 **Test de Censorship**: Vérifier si un site est bloqué dans certains pays.
* 📓 **Recherche Whois** : Effectuer une recherche d'informations Whois pour les noms de domaine ou les adresses IP
* 📀 **Recherche MAC** : Requête d'informations d'une adresse physique
* 🌗 **Mode sombre** : Bascule automatiquement entre les modes sombre et clair en fonction des paramètres du système, avec une option de basculement manuel.
* 📱 **Mode minimaliste** : Un mode optimisé pour les mobiles qui réduit la longueur de la page pour un accès rapide aux informations essentielles.
* 🔍 **Recherche d'informations sur l'adresse IP** : Fournit un outil pour interroger des informations sur n'importe quelle adresse IP.
Expand Down Expand Up @@ -101,6 +102,7 @@ Vous pouvez utiliser le programme sans ajouter de variables d'environnement, mai
| `IPAPIIS_API_KEY` | Non | `""` | Clé API pour IPAPI.is, utilisée pour obtenir des informations de géolocalisation sur l'adresse IP via IPAPI.is |
| `KEYCDN_USER_AGENT` | Non | `""` | Le nom de domaine lorsque vous utilisez KeyCDN, doit contenir le préfixe https. Utilisé pour obtenir des informations sur l'adresse IP via KeyCDN |
| `CLOUDFLARE_API` | Non | `""` | Clé API pour Cloudflare, utilisée pour obtenir des informations sur le système AS via Cloudflare |
| `MAC_LOOKUP_API_KEY` | Non | `""` | Clé API pour MAC Lookup, utilisée pour obtenir des informations sur l'adresse MAC via MAC Lookup |

### Utilisation des variables d'environnement dans un environnement Node

Expand Down
4 changes: 3 additions & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🧰 IP 工具箱

<a href="https://trendshift.io/repositories/5332" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5332" alt="jason5ng32%2FMyIP | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://trendshift.io/repositories/5332" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5332" alt="jason5ng32%2FMyIP | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>

![IPCheck.ing Banner](https://raw.githubusercontent.com/jason5ng32/MyIP/main/public/github/gh_banner.png)

Expand Down Expand Up @@ -43,6 +43,7 @@
* 🔦 **DNS 解析器**:从多个渠道对域名进行 DNS 解析,获取实时的解析结果,可用于污染判断
* 🚧 **封锁测试**:检查特定的网站在部分国家是否被封锁
* 📓 **Whois 查询**:对域名或 IP 进行 whois 信息查询
* 📀 **MAC 地址查询**:查询物理地址的归属信息
* 🌗 **暗黑模式**:根据系统设置自动切换暗黑/白天模式,也可以手动切换
* 📱 **简约模式**:为移动版提供的专门模式,缩短页面长度,快速查看最重要的信息
* 🔍 **查任意 IP 信息**:可以通过小工具查询任意 IP 的信息
Expand Down Expand Up @@ -103,6 +104,7 @@ docker run -d -p 18966:18966 --name myip --restart always jason5ng32/myip:latest
| `IPAPIIS_API_KEY` || `""` | IPAPI.is 的 API Key,用于通过 IPAPI.is 获取 IP 归属地信息 |
| `KEYCDN_USER_AGENT` || `""` | 使用 KeyCDN 时的域名,需包含 https 前缀。用于通过 KeyCDN 获取 IP 归属地信息 |
| `CLOUDFLARE_API` || `""` | Cloudflare 的 API Key,用于通过 Cloudflare 获取 AS 系统的信息 |
| `MAC_LOOKUP_API_KEY` || `""` | MAC 查询的 API Key,用于通过 MAC Lookup 获取 MAC 地址的归属信息 |

### 在 Node 环境里使用环境变量

Expand Down
78 changes: 78 additions & 0 deletions api/macchecker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { get } from 'https';
import { refererCheck } from '../common/referer-check.js';

const isValidMAC = (address) => {
const normalizedAddress = address.replace(/[:-]/g, '');
return normalizedAddress.length >= 6 && normalizedAddress.length <= 12 && /^[0-9A-Fa-f]+$/.test(normalizedAddress);
}

export default async (req, res) => {
// 限制只能从指定域名访问
const referer = req.headers.referer;
if (!refererCheck(referer)) {
return res.status(403).json({ error: referer ? 'Access denied' : 'What are you doing?' });
}

// 从请求中获取 IP 地址
let macAddress = req.query.mac;
if (!macAddress) {
return res.status(400).json({ error: 'No MAC address provided' });
} else {
macAddress = macAddress.replace(/:/g, '').replace(/-/g, '');
}

// 检查 IP 地址是否合法
if (!isValidMAC(macAddress)) {
return res.status(400).json({ error: 'Invalid MAC address' });
}


const token = process.env.MAC_LOOKUP_API_KEY || '';

const url_hasToken = `https://api.maclookup.app/v2/macs/${macAddress}?apiKey=${token}`;
const url_noToken = `https://api.maclookup.app/v2/macs/${macAddress}`;
const url = token ? url_hasToken : url_noToken;

get(url, apiRes => {
let data = '';
apiRes.on('data', chunk => data += chunk);
apiRes.on('end', async () => {
try {
const originalJson = JSON.parse(data);
if (originalJson.success !== true) {
return res.json({ success: false, error: originalJson.error || 'Data not found' });
}
const finalData = modifyData(originalJson);
res.json(finalData);
} catch (e) {
res.status(500).json({ error: 'Error parsing JSON' });
}
});
}).on('error', (e) => {
res.status(500).json({ error: e.message });
});
};


const modifyData = (data) => {
// 检查单播/多播以及本地/全球地址
const firstByte = parseInt(data.macPrefix.substring(0, 2), 16);
const isMulticast = (firstByte & 0x01) === 0x01;
const isLocal = (firstByte & 0x02) === 0x02;

data.isMulticast = isMulticast ? true : false;
data.isLocal = isLocal ? true : false;
data.isGlobal = !isLocal ? true : false;
data.isUnicast = !isMulticast ? true : false;
data.macPrefix = data.macPrefix? data.macPrefix : 'N/A';
data.company = data.company? data.company : 'N/A';
data.country = data.country? data.country : 'N/A';
data.address = data.address? data.address : 'N/A';
data.updated = data.updated? data.updated : 'N/A';
data.blockStart = data.blockStart? data.blockStart : 'N/A';
data.blockEnd = data.blockEnd? data.blockEnd : 'N/A';
data.blockSize = data.blockSize? data.blockSize : 'N/A';
data.blockType = data.blockType? data.blockType : 'N/A';

return data;
}
2 changes: 2 additions & 0 deletions backend-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { slowDown } from 'express-slow-down'
import whois from './api/whois.js';
import ipapiisHandler from './api/ipapiis.js';
import invisibilitytestHandler from './api/invisibilitytest.js';
import macChecker from './api/macchecker.js';

dotenv.config();

Expand Down Expand Up @@ -135,6 +136,7 @@ app.get('/api/dnsresolver', dnsResolver);
app.get('/api/whois', whois);
app.get('/api/ipapiis', ipapiisHandler);
app.get('/api/invisibility', invisibilitytestHandler);
app.get('/api/macchecker', macChecker);

// 使用查询参数处理所有配置请求
app.get('/api/configs', validateConfigs);
Expand Down
9 changes: 9 additions & 0 deletions frontend/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,15 @@ const ShortcutKeys = (isOriginalSite) => {
},
description: t('shortcutKeys.PingTest'),
},
{
keys: "M",
action: () => {
scrollToElement("AdvancedTools", 80);
advancedToolsRef.value.navigateAndToggleOffcanvas('/macchecker');
trackEvent('Nav', 'NavClick', 'MacChecker');
},
description: t('shortcutKeys.MacChecker'),
},
{
keys: "t",
action: () => {
Expand Down
7 changes: 6 additions & 1 deletion frontend/components/Advanced.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const cards = reactive([
{ path: '/dnsresolver', icon: '🔦', titleKey: 'dnsresolver.Title', noteKey: 'advancedtools.DNSResolverNote' },
{ path: '/censorshipcheck', icon: '🚧', titleKey: 'censorshipcheck.Title', noteKey: 'advancedtools.CensorshipCheck' },
{ path: '/whois', icon: '📓', titleKey: 'whois.Title', noteKey: 'advancedtools.Whois' },
{ path: '/macchecker', icon: '🗄️', titleKey: 'macchecker.Title', noteKey: 'advancedtools.MacChecker' },
]);
const cardInvisibilityTest = { path: '/invisibilitytest', icon: '🫣', titleKey: 'invisibilitytest.Title', noteKey: 'advancedtools.InvisibilityTest' };
Expand Down Expand Up @@ -121,9 +122,13 @@ const navigateAndToggleOffcanvas = (routePath) => {
trackEvent('Nav', 'NavClick', 'Whois');
openedCard.value = 5;
break;
case '/macchecker':
trackEvent('Nav', 'NavClick', 'MacChecker');
openedCard.value = 6;
break;
case '/invisibilitytest':
trackEvent('Nav', 'NavClick', 'InvisibilityTest');
openedCard.value = 6;
openedCard.value = 7;
break;
}
var offcanvas = new Offcanvas(document.getElementById('offcanvasTools'));
Expand Down
Loading

0 comments on commit 94f2e0a

Please sign in to comment.